// Copyright (C) 2006 David Griffiths // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "FastBreeder.h" #include "JackClient.h" static const int MAX_BUFFER=4096; FastBreeder::FastBreeder(OSCServer *server, unsigned int SampleRate) : m_CurrentSynth(0), m_SampleRate(SampleRate), m_Server(server) { m_SynthVec.push_back(new Synth(SampleRate)); //m_SynthVec.push_back(new Synth(SampleRate)); m_SynthVec[0]->Build("(sin (* (sin time ) 1000 ) )"); //m_SynthVec[1]->Build("(sin (* (sin time ) 1000 ) )"); NewOutputBuffer(); cerr<<"Starting FastBreeder"<SetCallback(Run,this); Jack->Attach("FastBreeder"); if (Jack->IsAttached()) { m_Left = Jack->AddOutputPort(); Jack->SetOutputBuf(m_Left, m_BufferVec[0]->Left.GetNonConstBuffer()); Jack->ConnectOutput(m_Left,"alsa_pcm:playback_1"); m_Right = Jack->AddOutputPort(); Jack->SetOutputBuf(m_Right, m_BufferVec[0]->Right.GetNonConstBuffer()); Jack->ConnectOutput(m_Right,"alsa_pcm:playback_2"); } } FastBreeder::~FastBreeder() { } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Interface thread side // These functions must not touch any data other than m_CH in order to be threadsafe void FastBreeder::NewOutputBuffer() { OutBuffer* NewBuffer = new OutBuffer; NewBuffer->Left.Allocate(MAX_BUFFER); NewBuffer->Right.Allocate(MAX_BUFFER); NewBuffer->Left.Zero(); NewBuffer->Right.Zero(); m_BufferVec.push_back(NewBuffer); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Audio thread side void FastBreeder::Run(void *RunContext, uint32 BufSize) { FastBreeder *Noise=static_cast(RunContext); Noise->ProcessCommands(); Noise->Process(BufSize); } void FastBreeder::ProcessCommands() { CommandRingBuffer::Command cmd; while (m_Server->Get(cmd)) { string name = cmd.Name; if (name=="/synth") { m_CurrentSynth=0;//!m_CurrentSynth; m_SynthVec[m_CurrentSynth]->Build(cmd.GetString(0)); //cerr<<"---------- "<::iterator i = m_BufferVec.begin(); i!=m_BufferVec.end(); i++) { if ((*i)->Left.GetLength()!=BufSize) { (*i)->Left.Allocate(BufSize); JackClient::Get()->SetOutputBuf(m_Left, (*i)->Left.GetNonConstBuffer()); } if ((*i)->Right.GetLength()!=BufSize) { (*i)->Right.Allocate(BufSize); JackClient::Get()->SetOutputBuf(m_Right, (*i)->Right.GetNonConstBuffer()); } (*i)->Left.Zero(); (*i)->Right.Zero(); } for (vector::iterator i = m_BufferVec.begin(); i!=m_BufferVec.end(); i++) { m_SynthVec[0]->Run((*i)->Left); //m_SynthVec[1]->Run((*i)->Right); (*i)->Right=(*i)->Left; } float cliplevel=0.1; for (vector::iterator i = m_BufferVec.begin(); i!=m_BufferVec.end(); i++) { for (unsigned int n=0; nLeft[n]*=0.1; (*i)->Right[n]*=0.1; if ((*i)->Left[n]<-cliplevel) (*i)->Left[n]=-cliplevel; if ((*i)->Left[n]>cliplevel) (*i)->Left[n]=cliplevel; if ((*i)->Right[n]<-cliplevel) (*i)->Right[n]=-cliplevel; if ((*i)->Right[n]>cliplevel) (*i)->Right[n]=cliplevel; } } }