/*************************************************************************** csound.cpp - description ------------------- begin : Wed Apr 5 2000 copyright : (C) 2000 by Volker Schroer email : huv.schroer@gmx.de ***************************************************************************/ /*************************************************************************** * * * 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. * ***************************************************************************/ #include "csound.h" #include "parameter.h" extern Parameter settings; static int inputCallback( void *inputBuffer, void *, unsigned long framesPerBuffer, PaTimestamp , void *userData ) { int SamplestoStore; SamplestoStore=framesPerBuffer; float *store; AudioBuffer *buffer = (AudioBuffer *) userData; float *inputData =(float *) inputBuffer; if (SamplestoStore != BUF_SIZE ) return 0; // Should never happen; store = buffer->audiobuffer + buffer->in; for (int i=0; i < SamplestoStore; i ++) *(store++) = *(inputData+ 2*i); buffer->in += BUF_SIZE; buffer->available++; if (buffer->in >= buffer->maxbuf) buffer->in -=buffer->maxbuf; return 0; } static int outputCallback( void *, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp , void *userData ) { int SamplestoSend; float *out; SamplestoSend=framesPerBuffer; AudioBuffer *buffer=(AudioBuffer *) userData; float *outputData= (float *) outputBuffer; if (buffer->available <= 0) { // printf("No buffers available\n"); return 0; // Should never happen } if(SamplestoSend != BUF_SIZE) { // printf("Not enough samples available\n"); return 0; // Should never happen } out=buffer->audiobuffer + buffer->out; for(int i=0;i < SamplestoSend; i++) { *outputData++ = (*out); //left and right channels should be the same *outputData++ = (*out++); } buffer->available--; // printf("buffer read %d\n",buffer->available); buffer->out +=BUF_SIZE; if (buffer->out >= buffer->maxbuf ) buffer->out =0; return 0; } CSound::CSound(int ptt = -1):Input(ptt) { stream=0; audio_buffer.maxbuf=3*BUF_SIZE; // We take 3 buffers audio_buffer.audiobuffer =new float[audio_buffer.maxbuf]; started=false; output=false; } CSound::~CSound() { if ( audio_buffer.audiobuffer >0) delete audio_buffer.audiobuffer; } int CSound::getSamples(double *sample,int anzahl) { if (audio_buffer.available >0) { float *x; audio_buffer.available--; audio_buffer.out += anzahl; if (audio_buffer.out >= audio_buffer.maxbuf) audio_buffer.out=0; x=&audio_buffer.audiobuffer[audio_buffer.out]; for(int i=0; i < anzahl; i++) *sample++=(*x++); return anzahl; } else return 0; } bool CSound::open_Device_read(QString *errorstring) { output=false; audio_buffer.in=0; audio_buffer.out=-BUF_SIZE; audio_buffer.available=0; if (settings.ActualInputDevice < 0 ) { *errorstring= QString(QObject::tr("No Inputdevice available or Inputdevice not selected")); return false; } saveSampleRate(settings.InputDevices[settings.ActualInputDevice]); PaError error=Pa_OpenStream( &stream, settings.InputDevices[settings.ActualInputDevice], 2, paFloat32, 0, paNoDevice, 0, paFloat32, 0, 11025, 4096, 0, paClipOff, // paNoFlag, inputCallback, &audio_buffer); if (error != 0 ) { *errorstring= QString(QObject::tr("Error opening stream \n"))+QString( Pa_GetErrorText(error) ); return false; } error=Pa_StartStream(stream); if (error != 0) { *errorstring= QString(QObject::tr("Error , couldn't start stream")); return false; } else started=true; return true; } bool CSound::open_Device_write(QString *errorstring) { if (settings.ActualOutputDevice < 0) { *errorstring= QString(QObject::tr("No Outputdevice available or Outputdevice not selected")); return false; } output=true; audio_buffer.in=-BUF_SIZE; audio_buffer.out=0; audio_buffer.available=0; saveSampleRate(settings.InputDevices[settings.ActualInputDevice]); PaError error=Pa_OpenStream( &stream, // PortAudioStream ** paNoDevice, // PaDeviceID Input 0, // Anzahl Input Channel paFloat32, // Format (float) 0, // InputDriverinfo * settings.OutputDevices[settings.ActualOutputDevice], // PaDeviceID Output 2, // Anzahl output Channel paFloat32, // Format (float) 0, // OutputDriverInfo * 11025, // SampleReate 4096, // Frames per Buffer 0, // number of Buffers 0= Minimum paClipOff, // Streams Flags outputCallback, // PortAudioCallback * &audio_buffer); // userdata * if (error != 0 ) { *errorstring= QString(QObject::tr("Error opening stream")); return false; } return true; } int CSound::putSamples(double *sample,int anzahl) { if (audio_buffer.available * BUF_SIZE < audio_buffer.maxbuf) { float *x; audio_buffer.in += anzahl; if (audio_buffer.in >= audio_buffer.maxbuf) audio_buffer.in=0; x=&audio_buffer.audiobuffer[audio_buffer.in]; for(int i=0; i < anzahl; i++) *x++=*sample++; audio_buffer.available++; // printf("Buffers filled %d\n",audio_buffer.available); return anzahl; } else return 0; } void CSound::PTT(bool mode) { int flags; int ii; flags= TIOCM_RTS|TIOCM_DTR; if (serial <0) // No serial Device selected { // No PTT, only start stream if (mode) { if ( !started ) { Pa_StartStream(stream); started = true; } } else { if ( started ) { Pa_AbortStream(stream); started = false; } } return; } if (mode) // PTT on { ii=ioctl(serial,TIOCMBIS,&flags); if ( !started ) { Pa_StartStream(stream); started = true; } } else { if ( started ) { Pa_AbortStream(stream); started = false; } ii=ioctl(serial,TIOCMBIC,&flags); } return; } bool CSound::close_Device() { //if (started) if (output) { // Wait for AudioBuffer to get empty while (audio_buffer.available> 0 ) usleep(10000); } if (started) Pa_StopStream(stream); if ( stream != 0 ) { Pa_CloseStream(stream); stream=0; } started=false; output = false; return true; } void CSound::saveSampleRate(PaDeviceID ID) { const PaDeviceInfo* Device; // Try to get the acutal Sample Rate Device =Pa_GetDeviceInfo(settings.InputDevices[settings.ActualInputDevice]); if (Device->numSampleRates == -1) OldSampleRate=Device->sampleRates[1]; // Range, select MaxRate else { if (Device->numSampleRates >0 ) OldSampleRate=Device->sampleRates [Device->numSampleRates-1]; else OldSampleRate=0; } } void CSound::restoreSampleRate() { if (output) { } else { } }