Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   File Members  

dev_sound.cpp

00001 /* MuSE - Multiple Streaming Engine
00002  * SoundDevice class interfacing Portaudio PABLIO library
00003  * Copyright (C) 2004 Denis Roio aka jaromil <jaromil@dyne.org>
00004  *
00005  * This source code is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Public License as published 
00007  * by the Free Software Foundation; either version 2 of the License,
00008  * or (at your option) any later version.
00009  *
00010  * This source code is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00013  * Please refer to the GNU Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Public License along with
00016  * this source code; if not, write to:
00017  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  
00019  "$Id: dev_sound.cpp,v 1.5 2004/12/15 18:18:06 jaromil Exp $"
00020  
00021  */
00022 
00023 #include <dev_sound.h>
00024 #include <pablio.h>
00025 #include <jutils.h>
00026 #include <generic.h>
00027 
00028 #define PA_SAMPLE_TYPE paInt16
00029 #define PA_SAMPLES_PER_FRAME 2
00030 #define PA_MAX_FRAMES 4096
00031 #define PA_NUM_SECONDS 5
00032 
00033 #ifdef HAVE_JACK
00034 int dev_jack_process(jack_nframes_t nframes, void *arg) {
00035   jack_nframes_t opframes;
00036   SoundDevice *dev = (SoundDevice*)arg;
00037   if(!dev->jack) return 0; // just return
00038   
00039   // take output from pipe and send it to jack
00040   dev->jack_out_buf = (jack_default_audio_sample_t*)
00041     jack_port_get_buffer(dev->jack_out_port,nframes);
00042   opframes = dev->jack_out_pipe->read
00043     (nframes * sizeof(float) * 2 , dev->jack_out_buf);
00044 
00045   // take input from jack and send it in pipe
00046   dev->jack_in_buf = (jack_default_audio_sample_t*)
00047     jack_port_get_buffer(dev->jack_in_port,nframes);
00048   dev->jack_in_pipe->write // does the float2int conversion in one pass
00049     (nframes * sizeof(float) * 2 , dev->jack_in_buf);
00050 
00051   return 0;
00052 }
00053 
00054 void dev_jack_shutdown(void *arg) {
00055   SoundDevice *dev = (SoundDevice*)arg;
00056   // close the jack channels
00057   dev->jack = false;
00058   jack_port_unregister(dev->jack_client, dev->jack_in_port);
00059   jack_port_unregister(dev->jack_client, dev->jack_out_port);
00060   jack_deactivate(dev->jack_client);
00061   delete dev->jack_in_pipe;
00062   delete dev->jack_out_pipe;
00063 }
00064 #endif
00065 
00066 SoundDevice::SoundDevice() {
00067   aInStream = NULL;
00068   aOutStream = NULL;
00069   jack = false;
00070   jack_in = false;
00071   jack_out = false;
00072 }
00073 
00074 SoundDevice::~SoundDevice() {
00075   close();
00076 }
00077 
00078 bool SoundDevice::pablio_input(bool state) {
00079   if(state && !aInStream) {
00080     err = OpenAudioStream( &aInStream, SAMPLE_RATE, PA_SAMPLE_TYPE,
00081                            (PABLIO_READ | PABLIO_STEREO) );
00082     if( err != paNoError) {
00083       Pa_Terminate();
00084       error("error opening input sound device: %s",Pa_GetErrorText( err ) );
00085       return false;
00086     } else
00087       info_input = Pa_GetDeviceInfo( Pa_GetDefaultInputDeviceID() );
00088 
00089   } else if(!state && aInStream) {
00090 
00091     CloseAudioStream(aInStream);
00092     aInStream = NULL;
00093     info_input = NULL;
00094 
00095   }
00096   return true;
00097 }
00098 
00099 bool SoundDevice::input(bool state) {
00100   bool res = false;
00101   if(jack) return true;
00102   if(!res) res = pablio_input(state);
00103   return res;
00104 }
00105 
00106 
00107 bool SoundDevice::pablio_output(bool state) {
00108   if(state && !aOutStream) {
00109     err = OpenAudioStream( &aOutStream, SAMPLE_RATE, PA_SAMPLE_TYPE,
00110                            (PABLIO_WRITE | PABLIO_STEREO) );
00111     if( err != paNoError) {
00112       Pa_Terminate();
00113       error("error opening output sound device: %s",Pa_GetErrorText( err ) );
00114       return false;
00115     } else
00116       info_output = Pa_GetDeviceInfo( Pa_GetDefaultOutputDeviceID() );
00117 
00118   } else if(!state && aOutStream) {
00119     
00120     CloseAudioStream(aOutStream);
00121     aOutStream = NULL;
00122     info_output = NULL;
00123 
00124   }
00125   return true;
00126 }
00127 
00128 bool SoundDevice::output(bool state) {
00129   bool res = false;
00130   if(jack) return true;
00131   if(!res) res = pablio_output(state);
00132   return res;
00133 }
00134 
00135 bool SoundDevice::open(bool read, bool write) {
00136 
00137   //  notice("detecting sound device");
00138 
00139 #ifdef HAVE_JACK
00140   // we try to open up a jack client
00141   jack_sample_size = sizeof(jack_default_audio_sample_t);
00142   if(!jack) // check if it is not allready on
00143     if( (jack_client = jack_client_new("MuSE")) !=0 ) {
00144       notice("jack audio daemon detected");
00145       act("hooking in/out sound channels");
00146       warning("this feature is still experimental and won't work!");
00147       warning("you need to stop jack and free the audio card");
00148       jack = true;
00149       jack_samplerate = jack_get_sample_rate(jack_client);
00150       jack_set_process_callback(jack_client, dev_jack_process, this);    
00151       jack_on_shutdown(jack_client,dev_jack_shutdown,this);
00152 
00153       jack_in_pipe = new Pipe();
00154       jack_in_pipe->set_output_type("copy_float_to_int16");
00155       jack_in_pipe->set_block(false,true);
00156 
00157       jack_out_pipe = new Pipe();
00158       jack_out_pipe->set_input_type("copy_int16_to_float");
00159       jack_in_pipe->set_block(true,false);
00160 
00161       // open the jack input channel
00162       jack_in_port = jack_port_register(jack_client, "capture",
00163                                         JACK_DEFAULT_AUDIO_TYPE,
00164                                         JackPortIsInput, 0);
00165       // open the jack output channel
00166       jack_out_port = jack_port_register(jack_client, "playback",
00167                                          JACK_DEFAULT_AUDIO_TYPE,
00168                                          JackPortIsOutput, 0);
00169       
00170       jack_activate(jack_client);
00171       return true;
00172     }
00173 #endif
00174   
00175   if( ! output(write) ) return false;
00176   
00177   if(info_output) func("output device: %s",info_output->name);
00178   else error("output device not available");
00179   
00180   if( ! input(read) ) return false;
00181   
00182   if(info_input) func("input device: %s",info_input->name);
00183   else error("input device not available");
00184 
00185   return true;
00186 }
00187 
00188 void SoundDevice::close() {
00189   if(aInStream)
00190     CloseAudioStream( aInStream);
00191   aInStream = NULL;
00192 
00193   if(aOutStream)
00194     CloseAudioStream( aOutStream);
00195   aOutStream = NULL;
00196 }
00197 
00198 int SoundDevice::read(void *buf, int len) {
00199   // len is in samples: 4*2 32bit stereo
00200   int res = -1;
00201 
00202   if(jack) {
00203 
00204     res = jack_in_pipe->read(len<<1,buf);
00205 
00206   } else if(aInStream) { // pablio
00207 
00208     // takes number of left and right frames (stereo / 2)
00209     res = ReadAudioStream( aInStream, buf, len);
00210 
00211   }  
00212   return res;
00213 }
00214 
00215 int SoundDevice::write(void *buf, int len) {
00216   // len is in samples, for bytes must *2 (16bit)
00217   int res = -1;
00218 
00219   if(jack) { // jack audio daemon
00220 
00221     res = jack_out_pipe->write(len<<1,buf);
00222 
00223   } else if(aOutStream) { // pablio
00224 
00225     // takes number of left and right frames (stereo / 2)
00226     res = WriteAudioStream( aOutStream, buf, len>>1);
00227 
00228   }
00229   return res;
00230 
00231 }

Generated on Thu Dec 16 12:28:21 2004 for MuSE by doxygen1.3