From aaded78641babc6649cd9cfb42747f47cd72cf96 Mon Sep 17 00:00:00 2001 From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Date: Thu, 21 Feb 2008 10:40:03 -0500 Subject: [PATCH] ALSA: capture and playback (Unix Read/Write) - READ COMMENTS Not implemented yet: ringtones, dtmf #### Recommended play devices names (alsa-project.org) #### http://www.alsa-project.org/main/index.php/DeviceNames Device: #default --> capture : too much noise playback : glitchs dmix #plug:front --> playback almost perfect capture :bad audio (noise noise noise !!!) dmix not enabled #plug:rear --> doesn't exist on my sound card (Error: unknown PCM device) #plug:center_lfe --> idem #plug:side --> idem If there is multiple sound cards on your system, you can select the one you prefer like that: plug:front:0 select the card 0, 0 refers to the number in /proc/asound/cards. plug:front:Intel with the name of the card My /proc/asound/cards: 0 [Intel ]: HDA-Intel - HDA Intel HDA Intel at 0xfdff4000 irq 23 ##### Device names not recommmended (alsa-project.org) These devices maps directly to the driver devices and doesn't handle an abstraction plughw --> playback almost perfect capture : noise plus weird behaviour dmix not enabled hw --> playback : not audible ( maybe no resampling ?? no format conversion ??) capture : XRUN mode dmix not enabled --- src/audio/audiolayer.cpp | 477 ++++++++++++++++++--------------------- src/audio/audiolayer.h | 22 +- src/audio/audiortp.cpp | 5 +- 3 files changed, 238 insertions(+), 266 deletions(-) diff --git a/src/audio/audiolayer.cpp b/src/audio/audiolayer.cpp index d892214c50..db39e5fc62 100644 --- a/src/audio/audiolayer.cpp +++ b/src/audio/audiolayer.cpp @@ -29,7 +29,9 @@ #include "../manager.h" #include "../user_cfg.h" -#define PCM_NAME_DEFAULT "plughw:0,0" +#define PCM_NAME_DEFAULT "default" +#define PCM_PAUSE 1 +#define PCM_RESUME 0 #ifdef SFL_TEST_SINE #include <cmath> @@ -41,9 +43,12 @@ , _micRingBuffer(SIZEBUF) , _defaultVolume(100) , _errorMessage("") - , _manager(manager) + , _manager(manager) + , _playback_handle( NULL ) + , _capture_handle( NULL ) + , device_closed( true ) { - _sampleRate = 8000; + //_sampleRate = 8000; _inChannel = 1; // don't put in stereo _outChannel = 1; // don't put in stereo @@ -65,33 +70,26 @@ // Destructor AudioLayer::~AudioLayer (void) { - if(_playback_handle != NULL) { - close_alsa(); - _playback_handle = NULL ; + device_closed = true; + if(_capture_handle){ + snd_pcm_drop( _capture_handle ); + snd_pcm_close( _capture_handle ); + _capture_handle = 0; + } + if(_playback_handle){ + snd_pcm_drop( _playback_handle ); + snd_pcm_close( _playback_handle ); + _playback_handle = 0; } #ifdef SFL_TEST_SINE delete [] table_; #endif } - void -AudioLayer::close_alsa (void) -{ - _debug(" Alsa close stream \n"); - //ost::MutexLock guard(_mutex); - snd_pcm_close(_playback_handle); -} - -bool -AudioLayer::hasStream(void) { - ost::MutexLock guard(_mutex); - return (_playback_handle!=0 ? true : false); -} - void + bool AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize) { - _indexIn = indexIn; _indexOut = indexOut; _sampleRate = sampleRate; @@ -102,98 +100,11 @@ AudioLayer::openDevice (int indexIn, int indexOut, int sampleRate, int frameSize _debug(" : sample rate=%5d, format=%s\n", _sampleRate, SFLPortaudioFormatString); _debug(" : frame per buffer=%d\n", FRAME_PER_BUFFER); - // Name of the PCM device + ost::MutexLock guard( _mutex ); // TODO: Must be dynamic - - // TODO: capture - // Capture stream - snd_pcm_stream_t capture_stream = SND_PCM_STREAM_CAPTURE; - - // Open the playback device - open_playback_device(PCM_NAME_DEFAULT); - - // Set up the parameters required to open a device: - init_hw_parameters(); - - device_info(); - - //ost::MutexLock guard(_mutex); -} - -void -AudioLayer::open_playback_device(std::string pcm_name) -{ - // Playback stream - snd_pcm_stream_t playback_stream = SND_PCM_STREAM_PLAYBACK; - - if(snd_pcm_open(&_playback_handle, pcm_name.c_str(), playback_stream, SND_PCM_NONBLOCK) < 0){ - _debug(" Error while opening PCM device %s\n", pcm_name.c_str()); - } - else - _debug(" Device %s successfully opened. \n", pcm_name.c_str()); -} - -void -AudioLayer::init_hw_parameters( ) -{ - int periods = 2; - snd_pcm_uframes_t periodSize = 8192; - unsigned int sr = 44100; //(unsigned int)sampleRate; - - // Information about the hardware - snd_pcm_hw_params_t *hwparams; - // Allocate the struct on the stack - snd_pcm_hw_params_alloca( &hwparams ); - // Allocate memory space - if(snd_pcm_hw_params_malloc( &hwparams) < 0) - _debug(" can not allocate hardware paramater structure. \n"); - // Init hwparams with full configuration space - if(snd_pcm_hw_params_any(_playback_handle, hwparams) < 0){ - _debug(" Can not configure this PCM device .\n"); - } - // Set access type - if(snd_pcm_hw_params_set_access( _playback_handle , hwparams , SND_PCM_ACCESS_RW_INTERLEAVED ) <0){ - _debug(" Error setting access. \n"); - } - // Set sample format - if(snd_pcm_hw_params_set_format( _playback_handle, hwparams , SND_PCM_FORMAT_S16_LE) < 0 ){ - _debug(" Error setting format. \n"); - } - // Set sample rate - if(snd_pcm_hw_params_set_rate_near( _playback_handle, hwparams, &sr, 0 ) <0 ) { - _debug(" Error setting sample rate. \n"); - } - if(_sampleRate != sr) - _debug(" The rate %i Hz is not supported by your hardware.\n ==> Using %i Hz instead. \n", _sampleRate, sr); - // Set number of channels - if (snd_pcm_hw_params_set_channels( _playback_handle, hwparams, _inChannel) < 0) - _debug(" Error setting channels. \n"); - // Set number of periods - if (snd_pcm_hw_params_set_periods( _playback_handle, hwparams, periods, 0) < 0) - _debug(" Error setting periods. \n "); - // Set buffer size - if(snd_pcm_hw_params_set_buffer_size( _playback_handle, hwparams, (periodSize * periods) >>2) < 0 ) - _debug(" Error setting buffer size. \n "); - // Apply hardware parameters to the device - if(snd_pcm_hw_params( _playback_handle, hwparams) < 0 ) - _debug(" Error setting HW params. \n "); - + return open_device( PCM_NAME_DEFAULT ); } -int -AudioLayer::device_info( void ) -{ - /*snd_pcm_info_t *info; - if(snd_pcm_info( _playback_handle , info) <0 ) { - _debug(" Can not gather infos on opened device. \n"); - return 0; - } - else{*/ - return 1; - // } -} - - int AudioLayer::getDeviceCount() { @@ -204,232 +115,292 @@ AudioLayer::getDeviceCount() void AudioLayer::startStream(void) { - - snd_pcm_prepare( _playback_handle ); - _debug(" ALSA start stream. \n"); - if( snd_pcm_state( _playback_handle ) == SND_PCM_STATE_PREPARED ) - snd_pcm_start( _playback_handle ); - else - _debug(" Device not ready to start. \n"); - //playSinusWave(); + // STATE PREPARED + ost::MutexLock guard( _mutex ); + _debug(" entry startStream() - c => %d - p => %d\n", snd_pcm_state(_capture_handle), snd_pcm_state( _playback_handle)); + snd_pcm_start( _capture_handle ) ; + snd_pcm_start( _playback_handle ) ; + // STATE RUNNING + _debug(" exit startStream() - c => %d - p => %d\n", snd_pcm_state(_capture_handle), snd_pcm_state( _playback_handle)); } void AudioLayer::stopStream(void) { - _debug(" Alsa stop stream. \n"); - ost::MutexLock guard(_mutex); - if( isStreamActive() ){ - // tells the device to stop reading - snd_pcm_drop(_playback_handle); - _mainSndRingBuffer.flush(); - _urgentRingBuffer.flush(); - _micRingBuffer.flush(); - } - else - _debug(" Device not running. \n" ); -} - - void -AudioLayer::playSinusWave( void ) -{ - unsigned char* data; - int pcmreturn, l1, l2; - short s1, s2; - int frames; - - data = (unsigned char*)malloc(8192); - frames = 8192 >> 2; - for(l1 = 0; l1 < 100; l1++) { - for(l2 = 0; l2 < frames; l2++) { - s1 = (l2 % 128) * 100 - 5000; - s2 = (l2 % 256) * 100 - 5000; - data[4*l2] = (unsigned char)s1; - data[4*l2+1] = s1 >> 8; - data[4*l2+2] = (unsigned char)s2; - data[4*l2+3] = s2 >> 8; - } - /* Write num_frames frames from buffer data to the PCM device pointed to by pcm_handle */ - /* writei for interleaved */ - /* writen for non-interleaved */ - while ((pcmreturn = snd_pcm_writei(_playback_handle, data, frames)) < 0) { - snd_pcm_prepare(_playback_handle); - _debug("<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n"); - } - } + ost::MutexLock guard( _mutex ); + _debug(" entry stopStream() - c => %d - p => %d\n", snd_pcm_state(_capture_handle), snd_pcm_state( _playback_handle)); + snd_pcm_drop( _capture_handle ); + snd_pcm_prepare( _capture_handle ); + snd_pcm_drop( _playback_handle ); + snd_pcm_prepare( _playback_handle ); + _debug(" exit stopStream() - c => %d - p => %d\n", snd_pcm_state(_capture_handle), snd_pcm_state( _playback_handle)); } - -//TODO void AudioLayer::sleep(int msec) { + //snd_pcm_wait(_playback_handle, msec); } -//TODO bool AudioLayer::isStreamActive (void) { - ost::MutexLock guard(_mutex); - if(snd_pcm_state(_playback_handle) == SND_PCM_STATE_RUNNING) + ost::MutexLock guard( _mutex ); + if(!device_closed) return true; else return false; } + int AudioLayer::putMain(void* buffer, int toCopy) { - play_alsa(buffer, toCopy); - //ost::MutexLock guard(_mutex); - /*int a = _mainSndRingBuffer.AvailForPut(); - if ( a >= toCopy ) { - return _mainSndRingBuffer.Put(buffer, toCopy, _defaultVolume); - } else { - _debug("Chopping sound, Ouch! RingBuffer full ?\n"); - return _mainSndRingBuffer.Put(buffer, a, _defaultVolume); - }*/ + ost::MutexLock guard( _mutex ); + if ( _playback_handle ) + write(buffer, toCopy); return 0; } void AudioLayer::flushMain() { - ost::MutexLock guard(_mutex); - _mainSndRingBuffer.flush(); } int AudioLayer::putUrgent(void* buffer, int toCopy) { - ost::MutexLock guard(_mutex); - if ( hasStream() ) { - int a = _urgentRingBuffer.AvailForPut(); - if ( a >= toCopy ) { - return _urgentRingBuffer.Put(buffer, toCopy, _defaultVolume); - } else { - return _urgentRingBuffer.Put(buffer, a, _defaultVolume); - } - } + ost::MutexLock guard( _mutex ); + if ( _playback_handle ) + //write(buffer, toCopy); return 0; } int AudioLayer::canGetMic() { - if ( hasStream() ) { - return _micRingBuffer.AvailForGet(); - } else { - return 0; + int avail; + if ( _capture_handle ) { + avail = snd_pcm_avail_update( _capture_handle ); + //printf("%d\n", avail ); + if(avail > 0) + return avail; + else + return 0; } + else + return 0; } int AudioLayer::getMic(void *buffer, int toCopy) { - if( hasStream() ) { - return _micRingBuffer.Get(buffer, toCopy, 100); - } else { + + if( _capture_handle ) + return read(buffer, toCopy); + else return 0; - } } void AudioLayer::flushMic() { - _micRingBuffer.flush(); } bool AudioLayer::isStreamStopped (void) { - ost::MutexLock guard(_mutex); - if(snd_pcm_state( _playback_handle ) == SND_PCM_STATE_XRUN) - return true; - else - return false; + ost::MutexLock guard( _mutex ); + return !(is_playback_active() & is_capture_active()); } void AudioLayer::toggleEchoTesting() { - ost::MutexLock guard(_mutex); + ost::MutexLock guard( _mutex ); _echoTesting = (_echoTesting == true) ? false : true; } -int -AudioLayer::audioCallback (const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer){ - SFLDataFormat *in = (SFLDataFormat *) inputBuffer; - SFLDataFormat *out = (SFLDataFormat *) outputBuffer; +////////////////////////////////////////////////////////////////////////////////////////////// +///////////////// ALSA PRIVATE FUNCTIONS //////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////// - if (_echoTesting) { - memcpy(out, in, framesPerBuffer*sizeof(SFLDataFormat)); - return framesPerBuffer*sizeof(SFLDataFormat); - } +bool +AudioLayer::isPlaybackActive(void) { + ost::MutexLock guard( _mutex ); + if( _playback_handle ) + return (snd_pcm_state(_playback_handle) == SND_PCM_STATE_RUNNING ? true : false); + else + return false; +} - int toGet; - int toPut; - int urgentAvail; // number of data right and data left - int normalAvail; // number of data right and data left - int micAvailPut; - unsigned short spkrVolume = _manager->getSpkrVolume(); - unsigned short micVolume = _manager->getMicVolume(); - - // AvailForGet tell the number of chars inside the buffer - // framePerBuffer are the number of data for one channel (left) - urgentAvail = _urgentRingBuffer.AvailForGet(); - if (urgentAvail > 0) { - // Urgent data (dtmf, incoming call signal) come first. - toGet = (urgentAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? urgentAvail : framesPerBuffer * sizeof(SFLDataFormat); - _urgentRingBuffer.Get(out, toGet, spkrVolume); - // Consume the regular one as well (same amount of bytes) - _mainSndRingBuffer.Discard(toGet); - } else { - AudioLoop* tone = _manager->getTelephoneTone(); - if ( tone != 0) { - tone->getNext(out, framesPerBuffer, spkrVolume); - } else if ( (tone=_manager->getTelephoneFile()) != 0 ) { - tone->getNext(out, framesPerBuffer, spkrVolume); - } else { - // If nothing urgent, play the regular sound samples - normalAvail = _mainSndRingBuffer.AvailForGet(); - toGet = (normalAvail < (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof(SFLDataFormat); - - if (toGet) { - _mainSndRingBuffer.Get(out, toGet, spkrVolume); - } else { - bzero(out, framesPerBuffer * sizeof(SFLDataFormat)); - } - } - } +bool +AudioLayer::isCaptureActive(void) { + ost::MutexLock guard( _mutex ); + if( _capture_handle ) + return (snd_pcm_state( _capture_handle) == SND_PCM_STATE_RUNNING ? true : false); + else + return false; +} - // Additionally handle the mic's audio stream - micAvailPut = _micRingBuffer.AvailForPut(); - toPut = (micAvailPut <= (int)(framesPerBuffer * sizeof(SFLDataFormat))) ? micAvailPut : framesPerBuffer * sizeof(SFLDataFormat); - //_debug("AL: Nb sample: %d char, [0]=%f [1]=%f [2]=%f\n", toPut, in[0], in[1], in[2]); - _micRingBuffer.Put(in, toPut, micVolume); - return toPut; + bool +AudioLayer::open_device(std::string pcm_name) +{ + int err; + snd_pcm_hw_params_t *hwparams = NULL; + unsigned int rate_in = _sampleRate; + unsigned int rate_out = _sampleRate; + int direction = 0; + snd_pcm_uframes_t period_size_in = 1024; + snd_pcm_uframes_t buffer_size_in = 2048; + snd_pcm_uframes_t period_size_out = 2048; + snd_pcm_uframes_t buffer_size_out = 4096; + snd_pcm_sw_params_t *swparams = NULL; + + _debug(" Opening capture device %s\n", pcm_name.c_str()); + if(err = snd_pcm_open(&_capture_handle, pcm_name.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0){ + _debug(" Error while opening capture device %s (%s)\n", pcm_name.c_str(), snd_strerror(err)); + return false; + } + if( err = snd_pcm_hw_params_malloc( &hwparams ) < 0 ) { + _debug(" Cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); + return false; + } + if( err = snd_pcm_hw_params_any(_capture_handle, hwparams) < 0) _debug(" Cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_access( _capture_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) _debug(" Cannot set access type (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_format( _capture_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) _debug(" Cannot set sample format (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_rate_near( _capture_handle, hwparams, &rate_in, &direction) < 0) _debug(" Cannot set sample rate (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_channels( _capture_handle, hwparams, 1) < 0) _debug(" Cannot set channel count (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_period_size_near( _capture_handle, hwparams, &period_size_out , &direction) < 0) _debug(" Cannot set period size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_buffer_size_near( _capture_handle, hwparams, &buffer_size_out ) < 0) _debug(" Cannot set buffer size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params( _capture_handle, hwparams ) < 0) _debug(" Cannot set hw parameters (%s)\n", snd_strerror(err)); + snd_pcm_hw_params_free( hwparams ); + + + _debug(" Opening playback device %s\n", pcm_name.c_str()); + if(err = snd_pcm_open(&_playback_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0){ + _debug(" Error while opening playback device %s (%s)\n", pcm_name.c_str(), snd_strerror(err)); + return false; + } + if( err = snd_pcm_hw_params_malloc( &hwparams ) < 0 ) { + _debug(" Cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); + return false; + } + if( err = snd_pcm_hw_params_any( _playback_handle, hwparams) < 0) _debug(" Cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_access( _playback_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) _debug(" Cannot set access type (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_format( _playback_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) _debug(" Cannot set sample format (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_rate_near( _playback_handle, hwparams, &rate_out, &direction) < 0) _debug(" Cannot set sample rate (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_channels( _playback_handle, hwparams, 1) < 0) _debug(" Cannot set channel count (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_period_size_near( _playback_handle, hwparams, &period_size_out , &direction) < 0) _debug(" Cannot set period size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params_set_buffer_size_near( _playback_handle, hwparams, &buffer_size_out ) < 0) _debug(" Cannot set buffer size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_hw_params( _playback_handle, hwparams ) < 0) _debug(" Cannot set hw parameters (%s)\n", snd_strerror(err)); + snd_pcm_hw_params_free( hwparams ); + + snd_pcm_uframes_t val; + snd_pcm_sw_params_alloca( &swparams ); + snd_pcm_sw_params_current( _playback_handle, swparams ); + + if( err = snd_pcm_sw_params_get_start_threshold( swparams, &val ) < 0 ) _debug(" Cannot get start threshold (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params_get_stop_threshold( swparams, &val ) < 0 ) _debug(" Cannot get stop threshold (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params_get_boundary( swparams, &val ) < 0 ) _debug(" Cannot get boundary (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params_set_silence_threshold( _playback_handle, swparams, 0 ) < 0 ) _debug(" Cannot set silence threshold (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params_set_silence_size( _playback_handle, swparams, 0 ) < 0 ) _debug(" Cannot set silence size (%s)\n", snd_strerror(err)); + if( err = snd_pcm_sw_params( _playback_handle, swparams ) < 0 ) _debug(" Cannot set sw parameters (%s)\n", snd_strerror(err)); + + device_closed = false; + + return true; +} + + bool +AudioLayer::is_playback_active( void ) +{ + if(snd_pcm_state(_playback_handle) == SND_PCM_STATE_RUNNING) + return true; + else + return false; } + bool +AudioLayer::is_capture_active( void ) +{ + if(snd_pcm_state(_capture_handle) == SND_PCM_STATE_RUNNING) + return true; + else + return false; +} int -AudioLayer::play_alsa(void* buffer, int length) +AudioLayer::write(void* buffer, int length) { - if(_playback_handle == NULL) + if(device_closed || _playback_handle == NULL) return 0; + int bytes; + snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames( _playback_handle, length); - snd_pcm_prepare( _playback_handle ); - if( snd_pcm_writei( _playback_handle, buffer, frames) < 0){ + if( bytes = snd_pcm_writei( _playback_handle, buffer, frames) < 0 ) { snd_pcm_prepare( _playback_handle ); - _debug(" Buffer underrun!!!\n"); + _debug(" Playback error (%s)\n", snd_strerror(bytes)); return 0; } return 1; } + int +AudioLayer::read( void* target_buffer, int toCopy) +{ + if(device_closed || _capture_handle == NULL) + return 0; + + int bytes; + snd_pcm_uframes_t frames = snd_pcm_bytes_to_frames( _capture_handle, toCopy); + if( bytes = snd_pcm_readi( _capture_handle, target_buffer, frames) < 0 ) { + int err = bytes; + switch(err){ + case EPERM: + _debug(" Capture EPERM (%s)\n", snd_strerror(bytes)); + handle_xrun_state(); + break; + case -ESTRPIPE: + _debug(" Capture ESTRPIPE (%s)\n", snd_strerror(bytes)); + snd_pcm_resume( _capture_handle); + break; + case -EAGAIN: + _debug(" Capture EAGAIN (%s)\n", snd_strerror(bytes)); + break; + case -EBADFD: + _debug(" Capture EBADFD (%s)\n", snd_strerror(bytes)); + break; + case -EPIPE: + _debug(" Capture EPIPE (%s)\n", snd_strerror(bytes)); + handle_xrun_state(); + break; + } + return 0; + } + return toCopy; +} + + + void +AudioLayer::handle_xrun_state( void ) +{ + snd_pcm_status_t* status; + snd_pcm_status_alloca( &status ); + + int res = snd_pcm_status( _capture_handle, status ); + if( res <= 0){ + if(snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN ){ + snd_pcm_drop( _capture_handle ); + snd_pcm_prepare( _capture_handle ); + snd_pcm_start( _capture_handle ); + } + } + else + _debug(" Get status failed\n"); +} diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h index 973eb6856f..09c8408e22 100644 --- a/src/audio/audiolayer.h +++ b/src/audio/audiolayer.h @@ -48,13 +48,15 @@ class AudioLayer { * @param sampleRate * @param frameSize */ - void openDevice(int, int, int, int); + bool openDevice(int, int, int, int); void startStream(void); void stopStream(void); void sleep(int); - bool hasStream(void); + bool isPlaybackActive( void ); + bool isCaptureActive( void ); bool isStreamActive(void); bool isStreamStopped(void); + void closeStream(); void flushMain(); int putMain(void* buffer, int toCopy); @@ -99,24 +101,22 @@ class AudioLayer { void toggleEchoTesting(); private: - void close_alsa (void); - int play_alsa( void* , int ); - int device_info( void ); - void init_hw_parameters( void ); - void open_playback_device( std::string ); + bool open_device( std::string ); + int write( void* , int ); + int read( void*, int ); + bool is_playback_active( void ); + bool is_capture_active( void ); + void handle_xrun_state( void ); RingBuffer _urgentRingBuffer; RingBuffer _mainSndRingBuffer; RingBuffer _micRingBuffer; ManagerImpl* _manager; // augment coupling, reduce indirect access // a audiolayer can't live without manager - //portaudio::MemFunCallbackStream<AudioLayer> *_stream; - snd_pcm_t* _playback_handle; - snd_pcm_state_t* playback_state; snd_pcm_t* _capture_handle; + bool device_closed; - int playback_callback(snd_pcm_sframes_t nframes); /** * Portaudio indexes of audio devices on which stream has been opened */ diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp index 58cb4fcb7a..393faa799b 100644 --- a/src/audio/audiortp.cpp +++ b/src/audio/audiortp.cpp @@ -318,9 +318,11 @@ try { int maxBytesToGet = _layerSampleRate * _layerFrameSize * sizeof(SFLDataFormat) / 1000; // available bytes inside ringbuffer int availBytesFromMic = audiolayer->canGetMic(); + //printf("%i \n", availBytesFromMic); // take the lowest int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet; + //printf("%i\n", bytesAvail); // Get bytes from micRingBuffer to data_from_mic int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat); int nb_sample_up = nbSample; @@ -427,7 +429,6 @@ try { audiolayer->putMain(toAudioLayer, nbSample * sizeof(SFLDataFormat)); - // Notify (with a beep) an incoming call when there is already a call countTime += time->getSecond(); if (Manager::instance().incomingCallWaiting() > 0) { @@ -543,7 +544,7 @@ try { int countTime = 0; // for receive TimerPort::setTimer(_layerFrameSize); - audiolayer->flushMic(); + //audiolayer->flushMic(); audiolayer->startStream(); _start.post(); _debug("- ARTP Action: Start\n"); -- GitLab