//******************************************************************************* //* audio_thread_fxn ** //******************************************************************************* //* Input Parameters: ** //* void *envByRef -- a pointer to an audio_thread_env structure ** //* as defined in audio_thread.h ** //* ** //* envByRef.quit -- when quit != 0, thread will cleanup and exit ** //* ** //* Return Value: ** //* void * -- AUDIO_THREAD_SUCCESS or AUDIO_THREAD_FAILURE as ** //* defined in audio_thread.h ** //******************************************************************************* void *audio_thread_fxn( void *envByRef ) { // Variables and definitions // ************************* // Thread parameters and return value audio_thread_env * envPtr = envByRef; // < see above > void * status = AUDIO_THREAD_SUCCESS; // < see above > // The levels of initialization for initMask #define INPUT_ALSA_INITIALIZED 0x1 #define INPUT_BUFFER_ALLOCATED 0x2 #define OUTPUT_ALSA_INITIALIZED 0x4 #define OUTPUT_BUFFER_ALLOCATED 0x8 #define RECORD_BUFFER_ALLOCATED 0x10 unsigned int initMask = 0x0; // Used to only cleanup items that were init'd // Input and output driver variables snd_pcm_t *pcm_capture_handle; snd_pcm_t *pcm_output_handle; // Handle for the PCM device snd_pcm_uframes_t exact_bufsize; // bufsize is in frames. Each frame is 4 bytes int blksize = BLOCKSIZE; // Raw input or output frame size in bytes int *outputBuffer = NULL; // Output buffer for driver to read from int *inputBuffer = NULL; // Input buffer for driver to read into int *recordBuffer = NULL; // Thread Create Phase -- secure and initialize resources // ****************************************************** // Setup audio input device // ************************ // Open an ALSA device channel for audio input exact_bufsize = blksize/BYTESPERFRAME; if( audio_io_setup( &pcm_capture_handle, SOUND_DEVICE_IN, SAMPLE_RATE, SND_PCM_STREAM_CAPTURE, &exact_bufsize ) == AUDIO_FAILURE ) { ERR( "Audio_input_setup failed in audio_thread_fxn\n\n" ); status = AUDIO_THREAD_FAILURE; goto cleanup; } DBG( "exact_bufsize = %d\n", (int) exact_bufsize); // Record that input OSS device was opened in initialization bitmask initMask |= INPUT_ALSA_INITIALIZED; blksize = exact_bufsize*BYTESPERFRAME; // Create input buffer to read into from OSS input device if( ( inputBuffer = malloc( blksize * sizeof(int) ) ) == NULL ) { ERR( "Failed to allocate memory for input block (%d)\n", blksize * sizeof(int) ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } DBG( "Allocated input audio buffer of size %d to address %p\n", blksize * sizeof(int), inputBuffer ); // Record that the input buffer was allocated in initialization bitmask initMask |= INPUT_BUFFER_ALLOCATED; // Initialize audio output device // ****************************** // Initialize the output ALSA device DBG( "pcm_output_handle before audio_output_setup = %d\n", (int) pcm_output_handle); exact_bufsize = blksize/BYTESPERFRAME; DBG( "Requesting bufsize = %d\n", (int) exact_bufsize); if( audio_io_setup( &pcm_output_handle, SOUND_DEVICE_OUT, SAMPLE_RATE, SND_PCM_STREAM_PLAYBACK, &exact_bufsize) == AUDIO_FAILURE ) { ERR( "audio_output_setup failed in audio_thread_fxn\n" ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } DBG( "pcm_output_handle after audio_output_setup = %d\n", (int) pcm_output_handle); DBG( "blksize = %d, exact_bufsize = %d\n", blksize, (int) exact_bufsize); blksize = exact_bufsize; // Record that input ALSA device was opened in initialization bitmask initMask |= OUTPUT_ALSA_INITIALIZED; // Create output buffer to write from into ALSA output device if( ( outputBuffer = malloc( blksize * sizeof(int) ) ) == NULL ) { ERR( "Failed to allocate memory for output block (%d)\n", blksize * sizeof(int) ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } DBG( "Allocated output audio buffer of size %d to address %p\n", blksize * sizeof(int), outputBuffer ); // Record that the output buffer was allocated in initialization bitmask initMask |= OUTPUT_BUFFER_ALLOCATED; long temp = (long)blksize * RECORDTIME; if( ( recordBuffer = malloc( temp * sizeof(int) ) ) == NULL ) { ERR( "Failed to allocate memory for record block (%d)\n", temp * sizeof(int) ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } DBG( "Allocated record audio buffer of size %d to address %p\n", temp * sizeof(int), recordBuffer ); // Record that the output buffer was allocated in initialization bitmask initMask |= RECORD_BUFFER_ALLOCATED; // Thread Execute Phase -- perform I/O and processing // ************************************************** // Get things started by sending some silent buffers out. int i; memset(outputBuffer, 0, blksize * sizeof(int)); // Clear the buffers memset(inputBuffer, 0, blksize * sizeof(int)); memset(recordBuffer, 0, temp * sizeof(int)); for(i=0; i<5; i++) { while ((snd_pcm_readi(pcm_capture_handle, inputBuffer, blksize/BYTESPERFRAME)) < 0) { snd_pcm_prepare(pcm_capture_handle); ERR( "<<< Pre Buffer Overrun >>>\n"); } } for(i=0; i<5; i++) { while ((snd_pcm_writei(pcm_output_handle, outputBuffer, exact_bufsize)) < 0) { snd_pcm_prepare(pcm_output_handle); ERR( "<<<Pre Buffer Underrun >>> \n"); } } // // Processing loop // DBG( "Entering audio_thread_fxn processing loop\n" ); int count = 0; while( !envPtr->quit ) { // Read capture buffer from ALSA input device if( snd_pcm_readi(pcm_capture_handle, inputBuffer, blksize/BYTESPERFRAME) < 0 ) { snd_pcm_prepare(pcm_capture_handle); ERR( "<<<<<<<<<<<<<<< Buffer Overrun >>>>>>>>>>>>>>>\n"); ERR( "Error reading the data from file descriptor %d\n", (int) pcm_capture_handle ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } memcpy(outputBuffer, inputBuffer, blksize * sizeof(int)); if ( envPtr->replay == 1 ) { int i; for (i = 0; i < blksize; i++) { outputBuffer[i] += recordBuffer[((count%RECORDTIME)*blksize)+i]; } } else { memcpy(&recordBuffer[((count%RECORDTIME)*blksize)], inputBuffer, blksize * sizeof(int)); } // Write output buffer into ALSA output device while (snd_pcm_writei(pcm_output_handle, outputBuffer, blksize/BYTESPERFRAME) < 0) { snd_pcm_prepare(pcm_output_handle); ERR( "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n"); status = AUDIO_THREAD_FAILURE; goto cleanup; } DBG("%d, ", count); count++; } DBG("\n"); DBG( "Exited audio_thread_fxn processing loop\n" ); // Thread Delete Phase -- free up resources allocated by this file // *************************************************************** cleanup: DBG( "Starting audio thread cleanup to return resources to system\n" ); // Close the audio drivers // *********************** // - Uses the initMask to only free resources that were allocated. // - Nothing to be done for mixer device, as it was closed after init. // Close input OSS device if( initMask & INPUT_ALSA_INITIALIZED ) if( audio_io_cleanup( pcm_capture_handle ) != AUDIO_SUCCESS ) { ERR( "audio_input_cleanup() failed for file descriptor %d\n", (int) pcm_capture_handle ); status = AUDIO_THREAD_FAILURE; } // Close output ALSA device if( initMask & OUTPUT_ALSA_INITIALIZED ) if( audio_io_cleanup( pcm_output_handle ) != AUDIO_SUCCESS ) { ERR( "audio_output_cleanup() failed for file descriptor %d\n", (int)pcm_output_handle ); status = AUDIO_THREAD_FAILURE; } // Free allocated buffers // ********************** // Free input buffer if( initMask & INPUT_BUFFER_ALLOCATED ) { DBG( "Freeing audio input buffer at location %p\n", inputBuffer ); free( inputBuffer ); DBG( "Freed audio input buffer at location %p\n", inputBuffer ); } // Free output buffer if( initMask & OUTPUT_BUFFER_ALLOCATED ) { free( outputBuffer ); DBG( "Freed audio output buffer at location %p\n", outputBuffer ); } // Free record buffer if( initMask & RECORD_BUFFER_ALLOCATED) { free( recordBuffer ); DBG( "Freed audio record buffer at location %p\n", recordBuffer ); } // Return from audio_thread_fxn function // ************************************* // Return the status at exit of the thread's execution DBG( "Audio thread cleanup complete. Exiting audio_thread_fxn\n" ); return status; }
int main() { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 5000000 / val; while (loops > 0) { loops--; rc = snd_pcm_readi(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } rc = write(1, buffer, size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes\n", rc); } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
ssize_t AudioStreamInALSA::read(void *buffer, ssize_t bytes) { AutoMutex lock(mLock); if (!mPowerLock) { acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioInLock"); mPowerLock = true; } acoustic_device_t *aDev = acoustics(); // If there is an acoustics module read method, then it overrides this // implementation (unlike AudioStreamOutALSA write). if (aDev && aDev->read) return aDev->read(aDev, buffer, bytes); snd_pcm_sframes_t n, frames = snd_pcm_bytes_to_frames(mHandle->handle, bytes); status_t err; do { n = snd_pcm_readi(mHandle->handle, buffer, frames); #ifdef DROPFRAME #ifdef DROPFRAME2 FrameNumber++; if (!(FrameNumber % 17) && (FrameNumber <= 1700)) { n = snd_pcm_readi(mHandle->handle, buffer, frames); } if (!(FrameNumber % 176)) { n = snd_pcm_readi(mHandle->handle, buffer, frames); } if (FrameNumber == 1764) { FrameNumber = 0; n = snd_pcm_readi(mHandle->handle, buffer, frames); } #else FrameNumber++; if (FrameNumber == 624/*137* rane@2012 07 20*/) { FrameNumber = 0; n = snd_pcm_readi(mHandle->handle, buffer, frames); } #endif #endif if (n < frames) { if (mHandle->handle) { if (n < 0) { n = snd_pcm_recover(mHandle->handle, n, 0); if (aDev && aDev->recover) aDev->recover(aDev, n); } else n = snd_pcm_prepare(mHandle->handle); } return static_cast<ssize_t>(n); } } while (n == -EAGAIN); return static_cast<ssize_t>(snd_pcm_frames_to_bytes(mHandle->handle, n)); }
int main() { long loops; int rc,i = 0; int size; FILE *fp ; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val,val2; int dir; snd_pcm_uframes_t frames; char *buffer; if( (fp =fopen("sound.wav","w")) < 0) printf("open sound.wav fial\n"); /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s/n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s/n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ printf("size = %d\n",size); buffer = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 10000000 / val; while (loops > 0) { loops--; rc = snd_pcm_readi(handle, buffer, frames); printf("%d\n",i++); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred/n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s/n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames/n", rc); } //rc = fwrite( buffer,1, size,fp); rc = write(1,buffer,size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes/n", rc); else printf("fwrite buffer success\n"); } /******************打印参数*********************/ snd_pcm_hw_params_get_channels(params, &val); printf("channels = %d\n", val); snd_pcm_hw_params_get_rate(params, &val, &dir); printf("rate = %d bps\n", val); snd_pcm_hw_params_get_period_time(params, &val, &dir); printf("period time = %d us\n", val); snd_pcm_hw_params_get_period_size(params, &frames, &dir); printf("period size = %d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_time(params, &val, &dir); printf("buffer time = %d us\n", val); snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val); printf("buffer size = %d frames\n", val); snd_pcm_hw_params_get_periods(params, &val, &dir); printf("periods per buffer = %d frames\n", val); snd_pcm_hw_params_get_rate_numden(params, &val, &val2); printf("exact rate = %d/%d bps\n", val, val2); val = snd_pcm_hw_params_get_sbits(params); printf("significant bits = %d\n", val); //snd_pcm_hw_params_get_tick_time(params, &val, &dir); printf("tick time = %d us\n", val); val = snd_pcm_hw_params_is_batch(params); printf("is batch = %d\n", val); val = snd_pcm_hw_params_is_block_transfer(params); printf("is block transfer = %d\n", val); val = snd_pcm_hw_params_is_double(params); printf("is double = %d\n", val); val = snd_pcm_hw_params_is_half_duplex(params); printf("is half duplex = %d\n", val); val = snd_pcm_hw_params_is_joint_duplex(params); printf("is joint duplex = %d\n", val); val = snd_pcm_hw_params_can_overrange(params); printf("can overrange = %d\n", val); val = snd_pcm_hw_params_can_mmap_sample_resolution(params); printf("can mmap = %d\n", val); val = snd_pcm_hw_params_can_pause(params); printf("can pause = %d\n", val); val = snd_pcm_hw_params_can_resume(params); printf("can resume = %d\n", val); val = snd_pcm_hw_params_can_sync_start(params); printf("can sync start = %d\n", val); /*******************************************************************/ snd_pcm_drain(handle); snd_pcm_close(handle); fclose(fp); free(buffer); return 0; }
/*---------------------------------------------------------------- TIesrFA_ALSA_thread This function is the thread function that reads audio sample data from the audio channel and puts the data into the circular buffers. --------------------------------*/ void* TIesrFA_ALSA_thread( void* aArg ) { int rtnval; int pcmStarted = FALSE; /* The argument to the thread is the TIesrFA instance */ TIesrFA_t * const aTIesrFAInstance = (TIesrFA_t * const) aArg; /* TIesrFA_ALSA specific data */ TIesrFA_ALSA_t * const ALSAData = (TIesrFA_ALSA_t * const) aTIesrFAInstance->impl_data; /* Start the capture of audio data by the audio channel. If it failed to start, then set the read_data flag to zero, indicating failure, and the thread will terminate. */ rtnval = snd_pcm_start( ALSAData->alsa_handle ); if( rtnval < 0 ) ALSAData->read_data = FALSE; else pcmStarted = TRUE; /* Notify main thread that TIesrFA thread has attempted to start the PCM. Success or failure is set in the read_data value. If failed, then the thread will terminate immediately. */ sem_post( &( ALSAData->start_semaphore ) ); /* Loop reading sample data until requested to stop */ while( ALSAData->read_data == TRUE ) { snd_pcm_sframes_t numSamples; /* Wait for audio data to become available. If no data in one second, then something bad has happened. */ rtnval = snd_pcm_wait( ALSAData->alsa_handle, 1000 ); if( rtnval == 0 ) { /* Timeout indicating some bad failure. */ continue; } /* PCM has indicated data is available. Get amount of data available */ numSamples = snd_pcm_avail_update( ALSAData->alsa_handle ); if( numSamples < 0 ) { /* Assume buffer overflow condition */ ALSAData->buffer_overflow = 1; /* Try to recover */ snd_pcm_prepare( ALSAData->alsa_handle ); continue; } /* Determine number of samples to read. Must not exceed buffer size. */ numSamples = numSamples > ALSAData->read_samples ? ALSAData->read_samples : numSamples; /* Read the samples from the PCM */ numSamples = snd_pcm_readi( ALSAData->alsa_handle, ALSAData->read_buffer, numSamples ); /* Transfer samples to circular frame buffers, or handle error on read. */ if( ALSAData->read_data == TRUE ) { if( numSamples > 0 ) { int numBytesRead = numSamples * ALSAData->sample_size; TIesrFA_ALSA_fillframes( aTIesrFAInstance, numBytesRead ); } else if( numSamples == -EPIPE ) { ALSAData->buffer_overflow = 1; snd_pcm_prepare( ALSAData->alsa_handle ); continue; } else { /* Some other failure */ continue; } } } /* The flag has been set to stop processing audio data, so terminate the thread */ if( pcmStarted ) snd_pcm_drop( ALSAData->alsa_handle ); return(void*) TIesrFA_ALSAErrNone; }
void CALSAAudioSource::ProcessAudio(void) { int err; if (m_audioSrcFrameNumber == 0) { // Start the device if ((err = snd_pcm_start(m_pcmHandle)) < 0) { error_message("Couldn't start the PCM device: %s", snd_strerror(err)); } } snd_pcm_status_t *status; snd_pcm_status_alloca(&status); // for efficiency, process 1 second before returning to check for commands for (int pass = 0; pass < m_maxPasses && m_stop_thread == false; pass++) { u_int8_t* pcmFrameBuffer; pcmFrameBuffer = (u_int8_t*)malloc(m_pcmFrameSize); // The alsa frames is not the same as the pcm frames used to feed the encoder // Calculate how many alsa frames is neccesary to read to fill one pcm frame snd_pcm_uframes_t num_frames = m_pcmFrameSize / (m_audioSrcChannels * sizeof(u_int16_t)); // Check how many bytes there is to read in the buffer, it will be used to calculate timestamp snd_pcm_status(m_pcmHandle, status); unsigned long avail_bytes = snd_pcm_status_get_avail(status) * (m_audioSrcChannels * sizeof(u_int16_t)); Timestamp currentTime = GetTimestamp(); Timestamp timestamp; // Read num_frames frames from the PCM device // pointed to by pcm_handle to buffer capdata. // Returns the number of frames actually read. // TODO On certain alsa configurations, e.g. when using dsnoop with low sample rate, the period gets too small. What to do about that? snd_pcm_sframes_t framesRead; if((framesRead = snd_pcm_readi(m_pcmHandle, pcmFrameBuffer, num_frames)) == -EPIPE) { snd_pcm_prepare(m_pcmHandle); // Buffer Overrun. This means the audio buffer is full, and not capturing // we want to make the timestamp based on the previous one // When we hit this case, we start using the m_timestampOverflowArray // This will give us a timestamp for when the array is full. // // In other words, if we have a full audio buffer (ie: it's not loading // any more), we start storing the current timestamp into the array. // This will let us "catch up", and have a somewhat accurate timestamp // when we loop around // // wmay - I'm not convinced that this actually works - if the buffer // cleans up, we'll ignore m_timestampOverflowArray if (m_timestampOverflowArray != NULL && m_timestampOverflowArray[m_timestampOverflowArrayIndex] != 0) { timestamp = m_timestampOverflowArray[m_timestampOverflowArrayIndex]; } else { timestamp = m_prevTimestamp + SrcSamplesToTicks(avail_bytes); } if (m_timestampOverflowArray != NULL) m_timestampOverflowArray[m_timestampOverflowArrayIndex] = currentTime; debug_message("audio buffer full !"); } else { if (framesRead < (snd_pcm_sframes_t) num_frames) { error_message("Bad audio read. Expected %li frames, got %li", num_frames, framesRead); free(pcmFrameBuffer); continue; } // buffer is not full - so, we make the timestamp based on the number // of bytes in the buffer that we read. timestamp = currentTime - SrcSamplesToTicks(SrcBytesToSamples(avail_bytes)); if (m_timestampOverflowArray != NULL) m_timestampOverflowArray[m_timestampOverflowArrayIndex] = 0; } //debug_message("alsa read"); #ifdef DEBUG_TIMESTAMPS debug_message("avail_bytes=%lu t="U64" timestamp="U64" delta="U64, avail_bytes, currentTime, timestamp, timestamp - m_prevTimestamp); #endif m_prevTimestamp = timestamp; if (m_timestampOverflowArray != NULL) { m_timestampOverflowArrayIndex = (m_timestampOverflowArrayIndex + 1) % m_audioMaxBufferFrames; } #ifdef DEBUG_TIMESTAMPS debug_message("pcm forward "U64" %u", timestamp, m_pcmFrameSize); #endif if (m_audioSrcFrameNumber == 0 && m_videoSource != NULL) { m_videoSource->RequestKeyFrame(timestamp); } m_audioSrcFrameNumber++; CMediaFrame *frame = new CMediaFrame(PCMAUDIOFRAME, pcmFrameBuffer, m_pcmFrameSize, timestamp); ForwardFrame(frame); } }
static DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamplesCaptured) { NOREF(pInterface); AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn; snd_pcm_sframes_t cAvail; int rc = drvHostALSAAudioGetAvail(pThisStrmIn->phPCM, &cAvail); if (RT_FAILURE(rc)) { LogFunc(("Error getting number of captured frames, rc=%Rrc\n", rc)); return rc; } if (!cAvail) /* No data yet? */ { snd_pcm_state_t state = snd_pcm_state(pThisStrmIn->phPCM); switch (state) { case SND_PCM_STATE_PREPARED: cAvail = audioMixBufFree(&pHstStrmIn->MixBuf); break; case SND_PCM_STATE_SUSPENDED: { rc = drvHostALSAAudioResume(pThisStrmIn->phPCM); if (RT_FAILURE(rc)) break; LogFlow(("Resuming suspended input stream\n")); break; } default: LogFlow(("No frames available, state=%d\n", state)); break; } if (!cAvail) { if (pcSamplesCaptured) *pcSamplesCaptured = 0; return VINF_SUCCESS; } } Assert(cAvail); size_t cbToRead = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cAvail); LogFlowFunc(("cbToRead=%zu, cAvail=%RI32\n", cbToRead, cAvail)); uint32_t cWrittenTotal = 0; snd_pcm_uframes_t cToRead; snd_pcm_sframes_t cRead; while ( cbToRead && RT_SUCCESS(rc)) { cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbToRead), AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, pThisStrmIn->cbBuf)); AssertBreakStmt(cToRead, rc = VERR_NO_DATA); cRead = snd_pcm_readi(pThisStrmIn->phPCM, pThisStrmIn->pvBuf, cToRead); if (cRead <= 0) { switch (cRead) { case 0: { LogFunc(("No input frames available\n")); rc = VERR_ACCESS_DENIED; break; } case -EAGAIN: /* * Don't set error here because EAGAIN means there are no further frames * available at the moment, try later. As we might have read some frames * already these need to be processed instead. */ cbToRead = 0; break; case -EPIPE: { rc = drvHostALSAAudioRecover(pThisStrmIn->phPCM); if (RT_FAILURE(rc)) break; LogFlowFunc(("Recovered from capturing\n")); continue; } default: LogFunc(("Failed to read input frames: %s\n", snd_strerror(cRead))); rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */ break; } } else { uint32_t cWritten; rc = audioMixBufWriteCirc(&pHstStrmIn->MixBuf, pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead), &cWritten); if (RT_FAILURE(rc)) break; uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten); Assert(cbToRead >= cbWritten); cbToRead -= cbWritten; cWrittenTotal += cWritten; } } if (RT_SUCCESS(rc)) { uint32_t cProcessed = 0; if (cWrittenTotal) rc = audioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, &cProcessed); if (pcSamplesCaptured) *pcSamplesCaptured = cWrittenTotal; LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 processed), rc=%Rrc\n", cWrittenTotal, cProcessed, rc)); } LogFlowFuncLeaveRC(rc); return rc; }
static void *dev_thread(void *arg) { // capture thread: keep reading and ring-buffering till told to quit int ret, frames, i, j, shift, bits, isfloat; int sample_bytes; uint32_t (*puller)(unsigned char **, int); S32 sample; double scale; snd_pcm_format_t format; int avail; sample_t fsample; unsigned char *buffer, *pt; ALSA_CARD *card; card = (ALSA_CARD *)arg; log_msg("ALSA: recv from %s '%s'\n", card->device, card->name); buffer = (unsigned char *)malloc(card->blocksize * QMX_CHANNELS * sizeof(float)); snd_pcm_prepare(card->handle); bits = snd_pcm_hw_params_get_sbits(card->hparams); sample_bytes = bits / 8; snd_pcm_hw_params_get_format(card->hparams, &format); if ((isfloat = snd_pcm_format_float(format))) scale = 1.0; else scale = pow(2.0 , 1 - bits); log_msg("ALSA: 1/scale %f [%d]\n", 1.0 / scale, bits); card->running = 1; card->ringbuf = jack_ringbuffer_create(sizeof(sample_t) * RB_SECS * sampling_rate * QMX_CHANNELS + 0.5); if (snd_pcm_format_big_endian(format) == 1) puller = bepull; else puller = lepull; shift = 8 * (sizeof(uint32_t) - sample_bytes); ret = snd_pcm_readi(card->handle, buffer, card->blocksize); // prime pump while (card->running) { if ((ret = snd_pcm_wait(card->handle, 1000)) < 0) { if (ret == -EPIPE) { log_msg("ALSA: wait: EPIPE, recover...\n"); try_recover(card, ret, buffer); } else if (ret == -ESTRPIPE) { log_msg("ALSA: wait: ESTRPIPE, recover...\n"); try_recover(card, ret, buffer); } else log_msg("ALSA: poll failed %s\n", strerror(errno)); continue; } else if (ret == 0) { log_msg("ALSA: card timeout...\n"); continue; } avail = snd_pcm_avail_update(card->handle); if (avail < 0) { if (avail == -EPIPE) { log_msg("ALSA: avail_update: EPIPE, recover...\n"); try_recover(card, avail, buffer); continue; } else { log_msg("ALSA: weird avail %d\n", avail); break; } } if (avail > card->blocksize) avail = card->blocksize; frames = snd_pcm_readi(card->handle, (void *)buffer, avail); if (frames < 0) { log_msg("ALSA: read failed %s\n", snd_strerror(frames)); } else if (frames != avail) { log_msg("ALSA: wanted %d got %d\n", avail, frames); } pt = buffer; for (i = 0; i < frames; i++) { for (j = 0; j < QMX_CHANNELS; j++) { sample.u = (*puller)(&pt, sample_bytes); if (isfloat) fsample = sample.f; else { if (shift) sample.s = (sample.s << shift) >> shift; fsample = sample.s * scale; } jack_ringbuffer_write(card->ringbuf, (const char *)&fsample, sizeof(sample_t)); } } } free(buffer); log_msg("ALSA: stopped %s '%s'\n", card->device, card->name); snd_pcm_drain(card->handle); return NULL; }
/* * snd_thread_fn(arg) -- * * This is the main function for the background recording thread. It reads the * captured samples in to a local buffer, and then copies it to the shared * ring buffer for the other threads. * * This function should never terminate during the lifetime of the server. * * Arguments: * - arg Unused * * Return value: * Should never return */ static void *snd_thread_fn(void *arg) { snd_pcm_t *pcmh = NULL; psize_t psize; const int maxframes = 128; int local_bufsize, nperiods, nframes, tmpsz; int nbytes, towrite, ret; char *local_buffer = NULL; LOG(2, "Sound thread created...\n"); /* * Initialize the audio hardware */ LOG(1, "Initializing capture device\n"); if (capture_init(&pcmh, global_options.device, &psize) < 0) { fprintf(stderr, "Badness happened\n"); abort(); } LOG(3, " Period size: %ld frames\n", psize.frames); LOG(3, " Period time: %d us\n", psize.us); /* * Allocate the global buffer and the local buffer */ nperiods = (global_options.sndhistory * 1000000L) / psize.us; nframes = nperiods * psize.frames; tmpsz = nframes * 2 * 2; /* 2 chan/frame, 2 bytes/chan */ local_bufsize = maxframes * 2 * 2; gbuffer = malloc(tmpsz); local_buffer = malloc(local_bufsize); gbufsize = tmpsz; gbufpos = 0; if (!gbuffer || !local_buffer) { fprintf(stderr, "Bad alloc\n"); abort(); } /* * Signal that we're done with initialization */ pthread_barrier_wait(&ginit_barrier); /* * Start dumping the audio in to the global buffer */ LOG(1, "Beginning to capture audio...\n"); while (1) { ret = snd_pcm_readi(pcmh, local_buffer, maxframes); if (ret == -EPIPE) { fprintf(stderr, "Buffer overrun\n"); snd_pcm_prepare(pcmh); } else if (ret < 0) { fprintf(stderr, "Read error: %s\n", snd_strerror(ret)); abort(); } else { nbytes = ret * 2 * 2; pthread_mutex_lock(&gbuflock); towrite = MIN(gbufsize - gbufpos, nbytes); memcpy(gbuffer + gbufpos, local_buffer, towrite); nbytes -= towrite; gbufpos += towrite; if (nbytes) { /* Wrap around */ memcpy(gbuffer, local_buffer + towrite, nbytes); gbufpos = nbytes; LOG(3, "Full audio buffer! Wrapping...\n"); } pthread_mutex_unlock(&gbuflock); } } free(gbuffer); free(local_buffer); return NULL; }
/***************************************************************************** * GrabAudio: Grab an audio frame *****************************************************************************/ static block_t* GrabAudio( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; int i_read, i_correct; block_t *p_block; if( p_sys->p_block ) p_block = p_sys->p_block; else p_block = block_New( p_demux, p_sys->i_max_frame_size ); if( !p_block ) { msg_Warn( p_demux, "cannot get block" ); return 0; } p_sys->p_block = p_block; /* ALSA */ i_read = snd_pcm_readi( p_sys->p_alsa_pcm, p_block->p_buffer, p_sys->i_alsa_chunk_size ); if( i_read <= 0 ) { int i_resume; switch( i_read ) { case -EAGAIN: break; case -EPIPE: /* xrun */ snd_pcm_prepare( p_sys->p_alsa_pcm ); break; case -ESTRPIPE: /* suspend */ i_resume = snd_pcm_resume( p_sys->p_alsa_pcm ); if( i_resume < 0 && i_resume != -EAGAIN ) snd_pcm_prepare( p_sys->p_alsa_pcm ); break; default: msg_Err( p_demux, "Failed to read alsa frame (%s)", snd_strerror( i_read ) ); return 0; } } else { /* convert from frames to bytes */ i_read *= p_sys->i_alsa_frame_size; } if( i_read <= 0 ) return 0; p_block->i_buffer = i_read; p_sys->p_block = 0; /* Correct the date because of kernel buffering */ i_correct = i_read; /* ALSA */ int i_err; snd_pcm_sframes_t delay = 0; if( ( i_err = snd_pcm_delay( p_sys->p_alsa_pcm, &delay ) ) >= 0 ) { size_t i_correction_delta = delay * p_sys->i_alsa_frame_size; /* Test for overrun */ if( i_correction_delta > p_sys->i_max_frame_size ) { msg_Warn( p_demux, "ALSA read overrun (%zu > %zu)", i_correction_delta, p_sys->i_max_frame_size ); i_correction_delta = p_sys->i_max_frame_size; snd_pcm_prepare( p_sys->p_alsa_pcm ); } i_correct += i_correction_delta; } else { /* delay failed so reset */ msg_Warn( p_demux, "ALSA snd_pcm_delay failed (%s)", snd_strerror( i_err ) ); snd_pcm_prepare( p_sys->p_alsa_pcm ); } /* Timestamp */ p_block->i_pts = p_block->i_dts = mdate() - INT64_C(1000000) * (mtime_t)i_correct / 2 / ( p_sys->b_stereo ? 2 : 1) / p_sys->i_sample_rate; return p_block; }
void * snd_record(void* voidargs) { struct snd_record_args* args = (snd_record_args*) voidargs; *args->returnObj.state = 0; long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; uint16_t *buffer; int* signalNewState = args->signalNewState; bool continuous_capture = args->duration <= 0 ? true : false; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, (const char*) args->dev_name.c_str(), SND_PCM_STREAM_CAPTURE, 0); pthread_cleanup_push(deallocate_srarg, voidargs); if (rc < 0) { fp_err(FPOL_PCM, "unable to open pcm device: %s", snd_strerror(rc)); fp_debug(FPOL_PCM, "dev_name: %s", (char*) args->dev_name.c_str()); args->returnObj.errorcode = 1; //pthread_cleanup_pop(1); //return NULL; pthread_exit(NULL); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 samples/second sampling rate (CD quality) */ val = args->samplingFrequency; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 1152; //32; // snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); std::cout << "\n" << getTime() << " snd_record: unable to set hw parameters: " << snd_strerror(rc) << "\n"; pthread_exit(NULL); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (uint16_t*) malloc(size); free_pcm_args fpa; fpa.handle = handle; fpa.buffer = buffer; pthread_cleanup_push(&free_pcm, (void*) &fpa); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = args->duration * 1000000 / val; *args->returnObj.state = 1; while (*signalNewState >= 0 && (loops > 0 || continuous_capture)) { loops--; rc = snd_pcm_readi(handle, (void**) buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { args->returnObj.error = std::string("error from read: ") + std::string(snd_strerror(rc)); std::cout << "\n" << getTime() << " snd_record(): error from read: " << snd_strerror(rc) << "\n"; break; } else if (rc != (int) frames) { fprintf(stderr, "short read, read %d frames\n", rc); } (*(args->periodbuffer))[*args->periodbufferfloat].initferryperiod(size, 2); memcpy((*args->periodbuffer)[*args->periodbufferfloat].period, buffer, (*args->periodbuffer)[*args->periodbufferfloat].length); (*args->periodbufferfloat)++; (*args->periodbufferfloat) %= *args->periodbufferlength; // if (rc != size) { // fprintf(stderr, "short write: wrote %d bytes\n", rc); // } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); pthread_cleanup_pop(0); *args->returnObj.state = -1; pthread_cleanup_pop(0); return NULL; }
qint64 QAlsaAudioInput::read(char* data, qint64 len) { // Read in some audio data and write it to QIODevice, pull mode if ( !handle ) return 0; int bytesRead = 0; int bytesInRingbufferBeforeRead = ringBuffer.bytesOfDataInBuffer(); if (ringBuffer.bytesOfDataInBuffer() < len) { // bytesAvaiable is saved as a side effect of checkBytesReady(). int bytesToRead = checkBytesReady(); if (bytesToRead < 0) { // bytesAvailable as negative is error code, try to recover from it. xrun_recovery(bytesToRead); bytesToRead = checkBytesReady(); if (bytesToRead < 0) { // recovery failed must stop and set error. close(); errorState = QAudio::IOError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); return 0; } } bytesToRead = qMin<qint64>(len, bytesToRead); bytesToRead = qMin<qint64>(ringBuffer.freeBytes(), bytesToRead); bytesToRead -= bytesToRead % period_size; int count=0; int err = 0; while(count < 5 && bytesToRead > 0) { char buffer[bytesToRead]; int chunks = bytesToRead / period_size; int frames = chunks * period_frames; if (frames > (int)buffer_frames) frames = buffer_frames; int readFrames = snd_pcm_readi(handle, buffer, frames); bytesRead = snd_pcm_frames_to_bytes(handle, readFrames); if (m_volume < 1.0f) QAudioHelperInternal::qMultiplySamples(m_volume, settings, buffer, buffer, bytesRead); if (readFrames >= 0) { ringBuffer.write(buffer, bytesRead); #ifdef DEBUG_AUDIO qDebug() << QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(bytesRead).arg(readFrames).toLatin1().constData(); #endif break; } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { errorState = QAudio::IOError; err = 0; break; } else { if(readFrames == -EPIPE) { errorState = QAudio::UnderrunError; err = snd_pcm_prepare(handle); } else if(readFrames == -ESTRPIPE) { err = snd_pcm_prepare(handle); } if(err != 0) break; } count++; } } bytesRead += bytesInRingbufferBeforeRead; if (bytesRead > 0) { // got some send it onward #ifdef DEBUG_AUDIO qDebug() << "frames to write to QIODevice = " << snd_pcm_bytes_to_frames( handle, (int)bytesRead ) << " (" << bytesRead << ") bytes"; #endif if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return 0; if (pullMode) { qint64 l = 0; qint64 bytesWritten = 0; while (ringBuffer.bytesOfDataInBuffer() > 0) { l = audioSource->write(ringBuffer.availableData(), ringBuffer.availableDataBlockSize()); if (l > 0) { ringBuffer.readBytes(l); bytesWritten += l; } else { break; } } if (l < 0) { close(); errorState = QAudio::IOError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); } else if (l == 0 && bytesWritten == 0) { if (deviceState != QAudio::IdleState) { errorState = QAudio::NoError; deviceState = QAudio::IdleState; emit stateChanged(deviceState); } } else { bytesAvailable -= bytesWritten; totalTimeValue += bytesWritten; resuming = false; if (deviceState != QAudio::ActiveState) { errorState = QAudio::NoError; deviceState = QAudio::ActiveState; emit stateChanged(deviceState); } } return bytesWritten; } else { while (ringBuffer.bytesOfDataInBuffer() > 0) { int size = ringBuffer.availableDataBlockSize(); memcpy(data, ringBuffer.availableData(), size); data += size; ringBuffer.readBytes(size); } bytesAvailable -= bytesRead; totalTimeValue += bytesRead; resuming = false; if (deviceState != QAudio::ActiveState) { errorState = QAudio::NoError; deviceState = QAudio::ActiveState; emit stateChanged(deviceState); } return bytesRead; } } return 0; }
//******************************************************************************* //* audio_thread_fxn ** //******************************************************************************* //* Input Parameters: ** //* void *envByRef -- a pointer to an audio_thread_env structure ** //* as defined in audio_thread.h ** //* ** //* envByRef.quit -- when quit != 0, thread will cleanup and exit ** //* ** //* Return Value: ** //* void * -- AUDIO_THREAD_SUCCESS or AUDIO_THREAD_FAILURE as ** //* defined in audio_thread.h ** //******************************************************************************* void *audio_thread_fxn( void *envByRef ) { // Variables and definitions // ************************* // Thread parameters and return value audio_thread_env * envPtr = envByRef; // < see above > void * status = AUDIO_THREAD_SUCCESS; // < see above > // The levels of initialization for initMask #define INPUT_ALSA_INITIALIZED 0x1 #define INPUT_BUFFER_ALLOCATED 0x2 #define OUTPUT_FILE_OPENED 0x4 unsigned int initMask = 0x0; // Used to only cleanup items that were init'd // Input and output driver variables snd_pcm_uframes_t exact_bufsize; snd_pcm_t *pcm_capture_handle; FILE * outfile = NULL; // Output file pointer (i.e. handle) int blksize = BLOCKSIZE; // Raw input or output frame size char *inputBuffer = NULL; // Input buffer for driver to read into // Thread Create Phase -- secure and initialize resources // ****************************************************** // Setup audio input device // ************************ // Open an ALSA device channel for audio input exact_bufsize = blksize/BYTESPERFRAME; if( audio_io_setup( &pcm_capture_handle, SOUND_DEVICE, SAMPLE_RATE, SND_PCM_STREAM_CAPTURE, &exact_bufsize ) == AUDIO_FAILURE ) { ERR( "Audio_input_setup failed in audio_thread_fxn\n\n" ); status = AUDIO_THREAD_FAILURE; goto cleanup; } DBG( "exact_bufsize = %d\n", (int) exact_bufsize); // Record that input OSS device was opened in initialization bitmask initMask |= INPUT_ALSA_INITIALIZED; blksize = exact_bufsize*BYTESPERFRAME; // Create input buffer to read into from OSS input device if( ( inputBuffer = malloc( blksize ) ) == NULL ) { ERR( "Failed to allocate memory for input block (%d)\n", blksize ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } DBG( "Allocated input audio buffer of size %d to address %p\n", blksize, inputBuffer ); // Record that the input buffer was allocated in initialization bitmask initMask |= INPUT_BUFFER_ALLOCATED; // Open audio output file // ********************** // Open a file for record outfile = fopen(OUTFILE, "w"); if( outfile == NULL ) { ERR( "Failed to open file %s\n", OUTFILE ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } DBG( "Opened file %s with FILE pointer = %p\n", OUTFILE, outfile ); // Record that input OSS device was opened in initialization bitmask initMask |= OUTPUT_FILE_OPENED; // Thread Execute Phase -- perform I/O and processing // ************************************************** // Processing loop DBG( "Entering audio_thread_fxn processing loop\n" ); while( !envPtr->quit ) { // Read capture buffer from ALSA input device if( snd_pcm_readi(pcm_capture_handle, inputBuffer, blksize/BYTESPERFRAME) < 0 ) { snd_pcm_prepare(pcm_capture_handle); ERR( "<<<<<<<<<<<<<<< Buffer Overrun >>>>>>>>>>>>>>>\n"); ERR( "Error reading the data from file descriptor %d\n", (int) pcm_capture_handle ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } if( fwrite( inputBuffer, sizeof( char ), blksize, outfile ) < blksize ) { ERR( "Error writing the data to FILE pointer %p\n", outfile ); status = AUDIO_THREAD_FAILURE; goto cleanup; } } DBG( "Exited audio_thread_fxn processing loop\n" ); // Thread Delete Phase -- free up resources allocated by this file // *************************************************************** cleanup: DBG( "Starting audio thread cleanup to return resources to system\n" ); // Close the audio drivers // *********************** // - Uses the initMask to only free resources that were allocated. // - Nothing to be done for mixer device, as it was closed after init. // Close input OSS device if( initMask & INPUT_ALSA_INITIALIZED ) if( audio_io_cleanup( pcm_capture_handle ) != AUDIO_SUCCESS ) { ERR( "audio_input_cleanup() failed for file descriptor %d\n", (int) pcm_capture_handle ); status = AUDIO_THREAD_FAILURE; } // Close output file if( initMask & OUTPUT_FILE_OPENED ) { DBG( "Closing output file at FILE ptr %p\n", outfile ); fclose( outfile ); } // Free allocated buffers // ********************** // Free input buffer if( initMask & INPUT_BUFFER_ALLOCATED ) { DBG( "Freeing audio input buffer at location %p\n", inputBuffer ); free( inputBuffer ); DBG( "Freed audio input buffer at location %p\n", inputBuffer ); } // Return from audio_thread_fxn function // ************************************* // Return the status at exit of the thread's execution DBG( "Audio thread cleanup complete. Exiting audio_thread_fxn\n" ); return status; }
void *ioProcessing(void *envByRef, void *apPtr){ // Key variables for DSP void * status = DSP_THREAD_SUCCESS; audio_params *ap = apPtr; // Gets the audio parameters dsp_thread_env *envPtr = envByRef; // Gets the dsp thread environment int err; // for capturing errors int errcnt =0; // for capturing errors int *filter_on = malloc(sizeof(int)); double * volume = malloc(sizeof(double)); int * cnote = malloc(sizeof(int)); short * avgpwr = malloc(sizeof(short)); int i; buffer *xnL = malloc(sizeof(buffer)); // Define circular buffers and allocate memory left channel xn buffer *xnR = malloc(sizeof(buffer)); // Define circular buffers and allocate memory right channel xn buffer *ynL = malloc(sizeof(buffer)); // Define circular buffers and allocate memory left channel yn buffer *ynR = malloc(sizeof(buffer)); // Define circular buffers and allocate memory right channel yn initBuffer(xnL); // Initialize circular buffer initBuffer(xnR); // Initialize circular buffer initBuffer(ynL); // Initialize circular buffer initBuffer(ynR); // Initialize circular buffer *filter_on = (*envPtr).filter_on; *volume = (*envPtr).volume; *cnote = (*envPtr).cnote; *avgpwr = (*envPtr).avgpwr; memset((*ap).outputBuffer, 0, (*ap).blksize); // Clear the output buffer DBG( "Starting IO Processing...\n" ); // Process a block just to start the DSP and skip the first frame dspBlockProcess((short *)(*ap).outputBuffer, (short *)(*ap).outputBuffer, xnL, xnR, (*ap).blksize/2, filter_on, volume, cnote, avgpwr); DBG( "Entering dspThread processing loop...\n" ); // Read capture buffer from ALSA input device (just to get things going) while( snd_pcm_readi((*ap).pcm_capture_handle, (*ap).inputBuffer, (*ap).exact_bufsize) < 0 ){ snd_pcm_prepare((*ap).pcm_capture_handle); ERR( "<<<<<<<<<<<<<<< Buffer Prime Overrun >>>>>>>>>>>>>>>\n"); ERR( "Error reading the data from file descriptor %d\n", (int) (*ap).pcm_capture_handle ); } memset((*ap).outputBuffer, 0, (*ap).blksize); // Clear the output buffer // Write output buffer into ALSA output device (just to get things going) for(i=0; i<2; i++) { while ((err = snd_pcm_writei((*ap).pcm_output_handle, (*ap).outputBuffer, (*ap).exact_bufsize)) < 0){ snd_pcm_prepare((*ap).pcm_output_handle); ERR( "<<<Pre Buffer Underrun >>> err=%d, errcnt=%d\n", err, errcnt); } } // begin DSP main loop while( !(*envPtr).quit ) { // check dynamic DSP parameters *filter_on = (*envPtr).filter_on; *volume = (*envPtr).volume; *cnote = (*envPtr).cnote; *avgpwr = (*envPtr).avgpwr; // Read capture buffer from ALSA input device while( snd_pcm_readi((*ap).pcm_capture_handle, (*ap).inputBuffer, (*ap).exact_bufsize) < 0 ){ snd_pcm_prepare((*ap).pcm_capture_handle); ERR( "<<<<<<<<<<<<<<< Buffer Prime Overrun >>>>>>>>>>>>>>>\n"); ERR( "Error reading the data from file descriptor %d\n", (int) (*ap).pcm_capture_handle ); } // Audio process // passing the data as short since we are processing 16-bit audio. dspBlockProcess((short *)(*ap).outputBuffer, (short *)(*ap).inputBuffer, xnL, xnR, (*ap).blksize/2, filter_on, volume, cnote, avgpwr); //(*envPtr).cnote = *cnote; (*envPtr).avgpwr = *avgpwr; // Write output buffer into ALSA output device errcnt = 0; // The Beagle gets an underrun error the first time it trys to write, // so ignore the first error and it appears to work fine. while ((err = snd_pcm_writei((*ap).pcm_output_handle, (*ap).outputBuffer, (*ap).exact_bufsize)) < 0) { snd_pcm_prepare((*ap).pcm_output_handle); //ERR( "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>> err=%d, errcnt=%d\n", err, errcnt); memset((*ap).outputBuffer, 0, (*ap).blksize); // Clear the buffer snd_pcm_writei((*ap).pcm_output_handle, (*ap).outputBuffer, (*ap).exact_bufsize); } } // Free up resources destroyBuffer(xnL); free(xnL); destroyBuffer(xnR); free(xnR); destroyBuffer(ynL); free(ynL); destroyBuffer(ynR); free(ynR); free(filter_on); free(volume); free(cnote); free(avgpwr); DBG( "Exited IO Processing loop\n" ); return status; }
int main() { int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; screen = reinterpret_cast<msgBlit *>(malloc(sizeof(msgBlit) + WIDTH * HEIGHT)); screen->cmd = CMD_BLIT; screen->x = 0; screen->y = 0; screen->w = WIDTH; screen->h = HEIGHT; pthread_t blitter; pthread_create(&blitter, nullptr, blitScreen, nullptr); fftw_complex *in, *out; fftw_plan plan; in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * FFTWSIZE); out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * FFTWSIZE); plan = fftw_plan_dft_1d(FFTWSIZE, in, out, FFTW_FORWARD, FFTW_ESTIMATE); /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "hw:1,0", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to FFTWSIZE frames. */ frames = FFTWSIZE; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); // /* We want to loop for 5 seconds */ // snd_pcm_hw_params_get_period_time(params, // &val, &dir); // const long one_second = 1000000 / val; // const long refresh = one_second / 30; double minVol[MAXPOS]; double maxVol[MAXPOS]; for(int i = 0; i < MAXPOS; ++i) { minVol[i] = maxVol[i] = 0; } while (1) { rc = snd_pcm_readi(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); continue; } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } else { for(int pos = 0; pos < FFTWSIZE; ++pos) { // printf("%d, %d, %d, %d\n", buffer[pos * 4], buffer[pos * 4 + 1], buffer[pos * 4 + 2], buffer[pos * 4 + 3]); in[pos][0] = buffer[pos * 4 + 1]; in[pos][1] = 0; } fftw_execute(plan); for(int pos = 0; pos < MAXPOS; ++pos) { double vol = 0; for(int i = 0; i < 1; i++) { vol += fabs(out[pos+i][0]) + fabs(out[pos+i][1]); } if(vol < minVol[pos]) minVol[pos] = vol; if(vol > maxVol[pos]) maxVol[pos] = vol; int level = log(1000 * (vol - minVol[pos]) / maxVol[pos]) * HEIGHT / 6.9; int xStart = pos * WIDTH / MAXPOS; int xEnd = (pos + 1) * WIDTH / MAXPOS; for(int x = xStart; x < xEnd; ++x) { int yCross = std::min(HEIGHT, std::max(0, HEIGHT - level)); for(int y = 0; y < yCross; ++y) { screen->data[y * WIDTH + x] = 0; } for(int y = yCross; y < HEIGHT; ++y) { screen->data[y * WIDTH + x] = 1; } } } } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
int main(int argc, char *argv[]) { int rc; int capsize; snd_pcm_hw_params_t *params; unsigned int val = 44100; unsigned int capusec; int dir; snd_pcm_uframes_t frames; char *capbuffer; int16_t *scapbuffer; char *capdev = "default"; char *fifonam; struct stat status; int readbytes = 0; int writebytes = 0; char *buf; size_t bufsize = 176400; int bufstart; int bufend; int bufused; int fillbuf = 1; int buffull = 0; int bufendtoend; int bufstarttoend; int capcount = 0; long power = 0; int prevpower = 0; int i; int silent = 1; int silentcount = 0; int soundcount = 0; char startcmd[1000] = ""; char endcmd[1000] = ""; int wrote = 0; int silentt = 100; extern char *optarg; extern int optind; int opt; int err = 0; pid_t pid, sid; char pidstr[10]; char pidfile[50]; int pidfd; // Ignore pipe signals signal(SIGPIPE, SIG_IGN); // Flush the hardware buffer on interrupt/term signal(SIGINT, myterm); signal(SIGTERM, myterm); // Process command-line options and arguments while ((opt = getopt(argc, argv, "d:b:s:e:t:D")) != -1) { switch (opt) { case 'd': capdev = optarg; break; case 'b': bufsize = atof(optarg) * val * 8; if (bufsize < 33280 || bufsize > 1764000) { mylog(LOG_ERR, "Invalid buffer. Range is 0.1-5.0 sec.\n"); goto error; } break; case 's': strcpy(startcmd, optarg); if (stat(startcmd, &status) != 0) { mylog(LOG_ERR, "Invalid start command: %s\n", startcmd); goto error; } strcat(startcmd, " &"); break; case 'e': strcpy(endcmd, optarg); if (stat(endcmd, &status) != 0) { mylog(LOG_ERR, "Invalid end command: %s\n", endcmd); goto error; } strcat(endcmd, " &"); break; case 't': silentt = atoi(optarg); if ((silentt < 1) || (silentt > 32767)) { mylog(LOG_ERR, "Invalid silence threshold. Range is 1-32767.\n"); goto error; } break; case 'D': daemonize = 1; break; case '?': err = 1; mylog(LOG_ERR, "Invalid option: %s\n", argv[optind - 1]); break; } } if ((optind + 1) != argc) err = 1; if (err) { if (!daemonize) { printf("\nUsage:\n %s [-d arg] [-b arg] [-s arg] " "[-e arg] [-t arg] [-D] FIFO\n" " -d : ALSA capture device ['default']\n" " -b : target buffer in seconds [.5]\n" " -s : command to run when sound detected\n" " -e : command to run when silence detected\n" " -t : silence threshold (1 - 32767, [100])\n" " -D : daemonize\n" " FIFO : path to a named pipe\n", argv[0]); } goto error; } mylog(LOG_INFO, "Starting up.\n"); fifonam = argv[argc - 1]; // Daemonize if (daemonize) { pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } else if (pid > 0) { exit(EXIT_SUCCESS); } umask(0); sid = setsid(); if (sid < 0) { mylog(LOG_ERR, "Error creating new session: %s\n", strerror(errno)); goto error; } if (chdir("/") != 0) { mylog(LOG_ERR, "Error on chdir /: %s\n", strerror(errno)); goto error; } } // Write the pidfile sprintf(pidfile, "/var/run/cpiped.pid"); sprintf(pidstr, "%d\n", getpid()); pidfd = open(pidfile, O_RDWR|O_CREAT, 0644); write(pidfd, pidstr, strlen(pidstr)); close(pidfd); // Open the FIFO for read first, so the open for write succeeds. readfd = open(fifonam, O_RDONLY | O_NONBLOCK); if (readfd <= 0) { mylog(LOG_ERR, "Error opening FIFO for read: %s\n", strerror(errno)); goto error; } if (fstat(readfd, &status) != 0) { mylog(LOG_ERR, "fstat error on FIFO (%s).\n", fifonam); goto error; } if (!S_ISFIFO(status.st_mode)) { mylog(LOG_ERR, "%s is not a FIFO.\n", fifonam); goto error; } writefd = open(fifonam, O_WRONLY); if (writefd <= 0) { mylog(LOG_ERR, "Error opening FIFO for write: %s\n", strerror(errno)); goto error; } close(readfd); // Set the FIFO size to 8192 bytes to minimize latency fcntl(writefd, F_SETPIPE_SZ, 8192); // Open PCM device for recording (capture). rc = snd_pcm_open(&handle, capdev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if (rc != 0) { mylog(LOG_ERR, "Unable to open pcm device: %s\n", snd_strerror(rc)); goto error; } snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(handle, params, 2); snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); // Set period size to 1024 frames. frames = 1024; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); // Write the parameters to the driver rc = snd_pcm_hw_params(handle, params); if (rc != 0) { mylog(LOG_ERR, "Unable to set hw parameters: %s\n", snd_strerror(rc)); goto error; } // Determine the elapsed time of one period snd_pcm_hw_params_get_period_time(params, &capusec, &dir); // Create a capture buffer large enough to hold one period snd_pcm_hw_params_get_period_size(params, &frames, &dir); capsize = frames * 4; // 2 bytes/sample, 2 channels capbuffer = calloc(capsize, sizeof(char)); scapbuffer = (int16_t*)capbuffer; // Determine write size writebytes = capsize - 32 ; // Write a bit less to make sure write controls pace // Create a ring buffer to handle clock mismatch bufsize++; // Add one byte to permit determination of empty/full states buf = calloc(bufsize, sizeof(char)); bufstart = 0; bufend = 0; while (1) { // Determine the amount of buffer used bufused = bufend - bufstart + (bufend < bufstart) * (bufsize - 1); //printf("size:%d, start:%d, end:%d, used:%d, wrote:%d\n", bufsize, bufstart, bufend, bufused, wrote); if (bufused < capsize) { // Buffer is almost empty, don't send to pipe mylog(LOG_INFO, "Filling buffer\n"); fillbuf = 1; } if (bufused > (int)bufsize - 1 - capsize) { // Buffer is almost full, don't store captured samples mylog(LOG_INFO, "Buffer full\n"); buffull = 1; } // Resume both capture storage and write to pipe when the buffer reaches half-full if ((fillbuf == 1) && (bufused > (int)bufsize / 2)) fillbuf = 0; if ((buffull == 1) && (bufused < (int)bufsize / 2)) buffull = 0; // Capture samples if (!wrote) // When not writing, wait a bit between captures. usleep(capusec * .95); rc = snd_pcm_readi(handle, capbuffer, frames); if (rc == -EPIPE) { // EPIPE means overrun mylog(LOG_NOTICE, "Overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc == -EAGAIN) { rc = 0; // Ignore "Not Available" errors } else if (rc < 0) { mylog(LOG_ERR, "Capture error: %s\n", snd_strerror(rc)); } // Compute RMS power level regularly if (capcount > 10 && rc > 0) { // Approx. every quarter second power = 0; for (i = 0; i < rc / 2; i++) { power += pow(scapbuffer[i], 2) + pow(scapbuffer[i + 1], 2); } power = sqrt(power/rc); capcount = 0; if (power > silentt) { soundcount++; silentcount = 0; } else { silentcount++; soundcount = 0; } if (silent && soundcount > 1) { silent = 0; mylog(LOG_INFO, "Sound detected. Last two values: %d, %d\n", prevpower, (int)power); if (strcmp(startcmd, "") != 0) { mylog(LOG_INFO, "Running '%s'\n", startcmd); if (system(startcmd) != 0) { mylog(LOG_ERR, "Error running start command.\n"); } } } if (!silent && silentcount > 55) { silent = 1; mylog(LOG_INFO, "Silence detected. Last two values: %d, %d\n", prevpower, (int)power); if (strcmp(endcmd, "") != 0) { mylog(LOG_INFO, "Running '%s'\n", endcmd); if (system(endcmd) != 0) { mylog(LOG_ERR, "Error running end command.\n"); } } } } prevpower = power; capcount++; if (!buffull && rc > 0) { // Store samples in buffer readbytes = rc * 4; bufendtoend = bufsize - bufend; if (readbytes <= bufendtoend) { // No wrap required memcpy(buf + bufend, capbuffer, readbytes); } else { // Wrap required memcpy(buf + bufend, capbuffer, bufendtoend); memcpy(buf, capbuffer + bufendtoend, readbytes - bufendtoend); } bufend = (bufend + readbytes) % bufsize; } wrote = 0; if (!fillbuf) { bufstarttoend = bufsize - bufstart; if (writebytes <= bufstarttoend) { // No wrap required rc = write(writefd, buf + bufstart, writebytes); if (rc == writebytes) wrote = 1; } else { // Wrap required rc = write(writefd, buf + bufstart, bufstarttoend); rc = write(writefd, buf, writebytes - bufstarttoend); if (rc == writebytes - bufstarttoend) wrote = 1; } if (wrote) { bufstart = (bufstart + writebytes) % bufsize; } else { bufstart = (bufstart + readbytes) % bufsize; // Keep buffer used constant } } } exit(EXIT_SUCCESS); error: if (readfd > 0) close(readfd); if (writefd > 0) close(writefd); mylog(LOG_INFO, "Stopping due to error."); exit(EXIT_FAILURE); }
int main(int argc, char* argv[]) { int rc; int size; snd_pcm_t *handle=NULL; snd_pcm_hw_params_t *params=NULL; unsigned int val = 48000; unsigned int den; snd_pcm_uframes_t frames = 1024; //unsigned int frames = 1024; short *buffer=NULL; unsigned int BAUD = 100; if(argc > 1) { if(!sscanf(argv[1], "%5u", &BAUD) || BAUD > 15000 || BAUD < 1) { fprintf(stderr, "Invalid BAUD specified, using default...\n"); BAUD = 100; } } rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(handle, params, 1); snd_pcm_hw_params_set_rate_near(handle, params, &val, 0); snd_pcm_hw_params_set_period_size_near(handle, params, &frames, 0); rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } snd_pcm_hw_params_get_period_size(params, &frames, 0); snd_pcm_hw_params_get_rate_numden(params, &val, &den); size = frames * 2; printf("frames: %lu\n", frames); buffer = (short *) malloc(size); //snd_pcm_hw_params_get_period_time(params, &val, &dir); printf("samples/sec: %u/%u\n", val, den); printf("BAUD: %d\n", BAUD); short time_buff[5]; double tick = 0.0; memset(time_buff, 0, 5); unsigned char byte_rec=0; int msg=0; int bit=0; unsigned short msg_len=0; unsigned short msg_read=0; const double er = 1.0/(2.0*val); int calibrate = 1; double ref_pow = 1.0; char* msg_string = NULL; while (1) { rc = snd_pcm_readi(handle, (void*)buffer, frames); if (rc == -EPIPE) { fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } //Process-------------------------------------------------------------------------- int offset = 0; while(offset < frames) { int i; double power =0.0; for(i=0;i<5;i++) { power += sqrt((double)time_buff[i]*time_buff[i])/5.0; if(i<4){time_buff[i]=time_buff[i+1];} } time_buff[4] = buffer[offset]; tick += (1.0/val); if(tick>=1.0/BAUD - er)// && tick<=1.0/BAUD + er) { tick-=1.0/BAUD; if((power>=(ref_pow+6000)) && (!calibrate)) { byte_rec = byte_rec >> 1; byte_rec = byte_rec | 0x80; } else { byte_rec = byte_rec >> 1; byte_rec = byte_rec & 0x7F; } if(calibrate) { static int c = 0; ref_pow += power/500; //if(power > ref_pow) // ref_pow = power; c++; if(c==500) { printf("Noise Threshold: %lf\n", ref_pow); calibrate=0; } } //if(byte_rec) printf("%x ", byte_rec); if(byte_rec == 0xAB && msg==0) { msg=1; printf("\nMsg: "); fflush(0); } if(msg==1) { if(bit==8) { bit = 1; switch(msg_read) { case 0: ((unsigned char*)&msg_len)[0] = byte_rec; msg_read++; break; case 1: ((unsigned char*)&msg_len)[1] = byte_rec; msg_string = malloc(msg_len+1); msg_string[msg_len] = '\0'; msg_read++; break; default: msg_string[msg_read-2]=byte_rec; msg_read++; putchar(byte_rec); fflush(0); if(msg_read==msg_len+2) { //printf("%s", msg_string); //fflush(0); free(msg_string); msg_string = NULL; msg = 0; msg_len = 0; bit = 0; msg_read = 0; byte_rec = 0; break; } } } else { bit++; } } }
static size_t read_(sox_format_t * ft, sox_sample_t * buf, size_t len) { priv_t * p = (priv_t *)ft->priv; snd_pcm_sframes_t i, n; size_t done; len = min(len, p->buf_len); for (done = 0; done < len; done += n) { do { n = snd_pcm_readi(p->pcm, p->buf, (len - done) / ft->signal.channels); if (n < 0 && recover(ft, p->pcm, (int)n) < 0) return 0; } while (n <= 0); i = n *= ft->signal.channels; switch (p->format) { case SND_PCM_FORMAT_S8: { int8_t * buf1 = (int8_t *)p->buf; while (i--) *buf++ = SOX_SIGNED_8BIT_TO_SAMPLE(*buf1++,); break; } case SND_PCM_FORMAT_U8: { uint8_t * buf1 = (uint8_t *)p->buf; while (i--) *buf++ = SOX_UNSIGNED_8BIT_TO_SAMPLE(*buf1++,); break; } case SND_PCM_FORMAT_S16: { int16_t * buf1 = (int16_t *)p->buf; if (ft->encoding.reverse_bytes) while (i--) *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_swapw(*buf1++),); else while (i--) *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(*buf1++,); break; } case SND_PCM_FORMAT_U16: { uint16_t * buf1 = (uint16_t *)p->buf; if (ft->encoding.reverse_bytes) while (i--) *buf++ = SOX_UNSIGNED_16BIT_TO_SAMPLE(lsx_swapw(*buf1++),); else while (i--) *buf++ = SOX_UNSIGNED_16BIT_TO_SAMPLE(*buf1++,); break; } case SND_PCM_FORMAT_S24: { int24_t * buf1 = (int24_t *)p->buf; while (i--) *buf++ = SOX_SIGNED_24BIT_TO_SAMPLE(*buf1++,); break; } case SND_PCM_FORMAT_U24: { uint24_t * buf1 = (uint24_t *)p->buf; while (i--) *buf++ = SOX_UNSIGNED_24BIT_TO_SAMPLE(*buf1++,); break; } case SND_PCM_FORMAT_S32: { int32_t * buf1 = (int32_t *)p->buf; while (i--) *buf++ = SOX_SIGNED_32BIT_TO_SAMPLE(*buf1++,); break; } case SND_PCM_FORMAT_U32: { uint32_t * buf1 = (uint32_t *)p->buf; while (i--) *buf++ = SOX_UNSIGNED_32BIT_TO_SAMPLE(*buf1++,); break; } default: lsx_fail_errno(ft, SOX_EFMT, "invalid format"); return 0; }
main(int argc, char *argv[]) { FILE *fp; int fd,arg; snd_pcm_t *handle; snd_pcm_hw_params_t *hw_params; int rate=8000; float f[WINDOW],hann[WINDOW],w[WINDOW],w2[WINDOW],s0,s1=0,tot; float ac[ORDER+1],lcp[ORDER+1],lsp[ORDER],l[ORDER],weight[ORDER],delta,d; short sample,s[160],buf[2000]; int i,j,n,b,toggle=1; float e,laste=0; int ebit=ETOPBIT, ebuff=0; int sound=0; // boolean start/stop float f2[FFT],min; float real[FFT],imag[FFT]; int dummy[100000]; float amp[WINDOW],pha[WINDOW]; int frame=0; SpeexPreprocessState *st; for (i=0; i<8; i++) report[i]=0; st = speex_preprocess_state_init(160, 8000); i=1; speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i); // i=1; // speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i); // e=.0; // speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &e); // e=.0; // speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &e); setup_twiddles(realtwiddle,imtwiddle,FFT); for (i=0; i<WINDOW; i++) f[i]=0; for (i=0; i<ORDER; i++) {last[i]=0; last2[i]=0;} for(i=0; i<WINDOW; i++) hann[i]=0.5-0.5*cos(2.0*M_PI*i/(WINDOW-1)); if (argc==2) training=atoi(argv[1]); fprintf(stderr,"training=%i\n",training); // exit(0); cbsize=0; start[0]=0; size[0]=0; if (training==0) if (fp=fopen("cb.txt","r")) { while(!feof(fp)) { fscanf(fp,"%i\n",&size[cbsize]); for (i=start[cbsize]; i<start[cbsize]+size[cbsize]; i++) { for (n=1; n<FF2-1; n++) fscanf(fp,"%f,",&cb[i][n]); fscanf(fp,"\n"); } start[cbsize+1]=start[cbsize]+size[cbsize]; cbsize++; } fclose(fp); } //for (i=0; i<cbsize; i++) printf("%i,\n",size[i]); exit(0); //--------------------------------- fp=fopen("/tmp/b.raw","w"); snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); snd_pcm_hw_params_malloc(&hw_params); snd_pcm_hw_params_any(handle, hw_params); snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_rate_near(handle, hw_params, &rate, 0); snd_pcm_hw_params_set_channels(handle, hw_params, 2); snd_pcm_hw_params(handle, hw_params); snd_pcm_hw_params_free(hw_params); snd_pcm_prepare(handle); //printf("sleep 1...\n"); sleep(1); printf("OK, go....\n"); while(1) { for (i=0; i<WINDOW-STEP; i++) f[i]=f[i+STEP]; // shift samples down if (toggle) { //read(fd,s,160*2); snd_pcm_readi(handle, buf, 160); for (i=0; i<160; i++) s[i]=buf[i*2]; speex_preprocess_run(st, s); } else bcopy(&s[80],s,80*2); toggle=!toggle; for (i=WINDOW-STEP,j=0; i<WINDOW; i++,j++) { sample=s[j]; s0=(float)sample; f[i]=s0-s1*EMPH; s1=s0; // 1.0 pre-emphasis fwrite(&sample,2,1,fp); } for (i=0; i<WINDOW; i++) w[i]=f[i]; // remove any DC level.... tot=0; for (i=0; i<WINDOW; i++) tot+=w[i]; tot/=WINDOW; for (i=0; i<WINDOW; i++) w[i]-=tot; for (i=0; i<WINDOW; i++) w[i]*=hann[i]; // window data autocorrelate(w,ac,WINDOW,ORDER); wld(&lpc[1],ac,ORDER); lpc[0]=1.0; // e=ac[0]; e=0;for(i=0; i<=ORDER; i++) e+=ac[i]*lpc[i]; if (e<0) e=0; if (e>TOL_OFF) ebuff|=ebit; else ebuff&=~ebit; // update energy bit-buffer ebit>>=1; if (ebit==0) ebit=ETOPBIT; // circular shift for (i=0; i<FFT; i++) {real[i]=0; imag[i]=0;} for (i=0; i<=ORDER; i++) real[i]=lpc[i]; simple_fft(real,imag,realtwiddle,imtwiddle,FFT); for (i=0; i<FF2; i++) { b=bin[i]; f2[i]=powf(real[b]*real[b]+imag[b]*imag[b],-0.5); //f2[i]=powf(f2[i],0.333333); //f2[i]=powf(f2[i],1.2); f2[i]=logf(f2[i]); } // spectral tilt compensation... for (i=1; i<FF2; i++) f2[i]=f2[i]*(float)(i+TILT)/TILT; // fold down to 9 bins... /* if (f2[FF2-2]>f2[FF2-3]) f2[FF2-3]=f2[FF2-2]; f2[FF2-2]=0; if (f2[FF2-4]>f2[FF2-5]) f2[FF2-5]=f2[FF2-4]; f2[FF2-4]=0; if (f2[FF2-9]>f2[FF2-10]) f2[FF2-10]=f2[FF2-9]; f2[FF2-9]=0; if (f2[FF2-11]>f2[FF2-12]) f2[FF2-12]=f2[FF2-11]; f2[FF2-11]=0; if (f2[FF2-13]>f2[FF2-14]) f2[FF2-14]=f2[FF2-13]; f2[FF2-13]=0; if (f2[FF2-15]>f2[FF2-16]) f2[FF2-16]=f2[FF2-15]; f2[FF2-15]=0; */ for (i=0; i<FF2; i++) { if (f2[i]>6.0) f2[i]=6.0; f2[i]*=100.0; } if (TRACE) { fprintf(stderr,"%.f,",e); for (i=1; i<FF2-1; i++) fprintf(stderr,"%.f,",f2[i]); fprintf(stderr,"\n");} // calculate frame delta.... delta=0; for (i=1; i<FF2-1; i++) {d=f2[i]-last[i]; delta+=d*d;} //printf("delta=%f\n",delta); if (sound==0 && e>TOL_ON && frame>200) { // start recording... bcopy(last2,&word[wsize],FF2*4); wsize++; bcopy(last,&word[wsize],FF2*4); wsize++; sound=1; wsize=0; bcopy(f2,&word[wsize],FF2*4); wsize++; bcopy(last,last2,FF2*4); bcopy(f2,last,FF2*4); } else if (sound==1 && e>TOL_OFF) { // continue reading word... bcopy(f2,&word[wsize],FF2*4); wsize++; if (wsize>200) wsize=200; bcopy(last,last2,FF2*4); bcopy(f2,last,FF2*4); } else if (sound==1 && ebuff==0) { // finised reading word // wsize-=8; // remove training silence (2 frame buffer) if (wsize>4 && wsize<50) { if (training>0) train(); else closest(); } sound=0; wsize=0; bcopy(last,last2,FF2*4); bcopy(f2,last,FF2*4); } //for (i=1; i<FF2-1; i++) printf("%.0f,",f2[i]); printf(" e=%f\n",e); laste=e; frame++; if (frame==37800) exit(0); } }
//音频采集线程 void * capture_audio_thread(void *para) { int fdsound = 0; int readbyte = 0; #if RECORD_CAPTURE_PCM FILE *fp = fopen("capture.pcm", "wb"); #endif #if SILK_AUDIO_CODEC SKP_uint8 encode[MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES]; #endif #if SILK_AUDIO_CODEC init_silk_encoder();//初始化silk codec printf("end of init silk encoder\n"); #endif #if (SOUND_INTERFACE == SOUND_OSS) fdsound = open("/dev/dsp", O_RDONLY); if(fdsound<0) { perror("以只写方式打开音频设备"); //return; } printf("设置读音频设备参数 setup capture audio device parament\n"); ioctl(fdsound, SNDCTL_DSP_SPEED, &Frequency);//采样频率 ioctl(fdsound, SNDCTL_DSP_SETFMT, &format);//音频设备位宽 ioctl(fdsound, SNDCTL_DSP_CHANNELS, &channels);//音频设备通道 ioctl(fdsound, SNDCTL_DSP_SETFRAGMENT, &setting);//采样缓冲区 while(flag_capture_audio) { if((readbyte=read(fdsound, pWriteHeader->buffer_capture, SAMPLERATE/1000*READMSFORONCE*sizeof(short))) < 0) { perror("读声卡数据"); } else { //printf("readbyte=%d\n", readbyte); #if RECORD_CAPTURE_PCM fwrite(pWriteHeader->buffer_capture, SAMPLERATE/1000*READMSFORONCE*sizeof(short), 1, fp); #endif traceprintf("发送信号量 sem_capture\n"); pWriteHeader->FrameNO = FrameNO++; time(&(pWriteHeader->time)); //printf("cNO:%d, readbyte=%d,压缩后大小%d,pWriteHeader->vad=%d\n", pWriteHeader->FrameNO, readbyte, pWriteHeader->count_encode, pWriteHeader->vad); pthread_mutex_lock(&mutex_lock); n++; pWriteHeader->Valid = 1; pthread_mutex_unlock(&mutex_lock); pWriteHeader = pWriteHeader->pNext; sem_post(&sem_capture); } } close(fdsound); #elif (SOUND_INTERFACE == SOUND_ALSA) printf("alsa xxxxxxxxxxxxxxx\n"); struct timeval tv; struct timezone tz; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "plughw:0,0", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } snd_pcm_hw_params_alloca(¶ms);/* Allocate a hardware parameters object. */ snd_pcm_hw_params_any(handle, params);/* Fill it in with default values. */ /* Set the desired hardware parameters. */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);/* Interleaved mode */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);/* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_channels(handle, params, CHANNELS);/* Two channels (stereo), On for mono */ val = SAMPLERATE; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);/* SAMPLERATE bits/second sampling rate */ frames = SAMPLERATE/1000*READMSFORONCE; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);/* Set period size to SAMPLES_FOR_EACH_TIME frames. */ /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n",snd_strerror(rc)); exit(1); } snd_pcm_hw_params_get_period_size(params, &frames, &dir);/* Use a buffer large enough to hold one period */ #if 0 size = frames * sizeof(short) * CHANNELS; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); #endif snd_pcm_hw_params_get_period_time(params, &val, &dir);/* We want to loop for 5 seconds */ while(flag_capture_audio) { rc = snd_pcm_readi(handle, pWriteHeader->buffer_capture, frames); printf("read rc=%d\n", rc); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } #if RECORD_CAPTURE_PCM fwrite(pWriteHeader->buffer_capture, SAMPLERATE/1000*READMSFORONCE*sizeof(short), 1, fp); #endif #if 0 #if DEBUG_SAVE_CAPTURE_PCM rc = fwrite(pWriteHeader->buffer_capture, frames*sizeof(short), 1, fp); if(rc != 1) { fprintf(stderr, "write error %d\n", rc); } #endif #endif #if SILK_AUDIO_CODEC /* max payload size */ int nbBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES; /* Silk Encoder */ ret = SKP_Silk_SDK_Encode(psEnc, &encControl, pWriteHeader->buffer_capture, (SKP_int16)SAMPLERATE/1000*READMSFORONCE, pWriteHeader->buffer_encode, &nbBytes); pWriteHeader->count = nbBytes; printf("ret=%d, nbBytes=%d\n", ret, nbBytes); if(ret) { printf( "SKP_Silk_Encode returned %d, nbBytes=%d\n", ret, nbBytes); //break; } #endif #if SPEEX_AUDIO_CODEC speex_bits_reset(&bits); /*Encode the frame*/ speex_encode_int(state, pWriteHeader->buffer_capture, &bits); /*Copy the bits to an array of char that can be written*/ nbBytes = speex_bits_write(&bits, cbits, 200); printf("压缩后大小 %d\n", nbBytes); #endif sem_post(&sem_capture); sem_post(&sem_capture); gettimeofday(&tv, &tz); //((AUDIOBUFFER*)(pWriteHeader->buffer_capture))->FrameNO = FrameNO++; //((AUDIOBUFFER*)(pWriteHeader->buffer))->sec = tv.tv_sec; //((AUDIOBUFFER*)(pWriteHeader->buffer))->usec = tv.tv_usec; //printf("capture NO=%5d \n", FrameNO); pthread_mutex_lock(&mutex_lock); //pWriteHeader = pWriteHeader->pNext; pWriteHeader->Valid = 1; n++; pthread_mutex_unlock(&mutex_lock); pWriteHeader = pWriteHeader->pNext; sem_post(&sem_capture); //traceprintf("发送信号量 sem_capture\n"); } snd_pcm_drain(handle); snd_pcm_close(handle); #if 0 free(buffer); #endif #endif #if RECORD_CAPTURE_PCM fclose(fp); #endif printf("音频采集线程已经关闭 audio capture thread is closed\n"); return NULL; }
static void alsa_sig_io(snd_async_handler_t * h) { /* Previous sample */ static unsigned char ps = 0x80; /* Count samples with similar level (to detect pule/space length), 24.8 fp */ static unsigned sample_count = 0; /* Current signal level (dynamically changes) */ static unsigned signal_level = 0; /* Current state (pulse or space) */ static unsigned signal_state = 0; /* Signal maximum and minimum (used for "zero" detection) */ static unsigned char signal_max = 0x80, signal_min = 0x80; /* Non-zero if we're in zero crossing waiting state */ static char waiting_zerox = 0; /* Store sample size, as our sample buffer will represent shorts or chars */ unsigned char bytes_per_sample = (alsa_hw.format == SND_PCM_FORMAT_S16_LE ? 2 : 1); int i, err; char buff[READ_BUFFER_SIZE]; snd_pcm_sframes_t count; /* The value to multiply with number of samples to get microseconds * (fixed-point 24.8 bits). */ unsigned mulconst = 256000000 / alsa_hw.rate; /* Maximal number of samples that can be multiplied by mulconst */ unsigned maxcount = (((PULSE_MASK << 8) | 0xff) / mulconst) << 8; /* First of all, check for underrun. This happens, for example, when * the X11 server starts. If we won't, recording will stop forever. */ snd_pcm_state_t state = snd_pcm_state(alsa_hw.handle); switch (state) { case SND_PCM_STATE_SUSPENDED: while ((err = snd_pcm_resume(alsa_hw.handle)) == -EAGAIN) /* wait until the suspend flag is released */ sleep(1); if (err >= 0) goto var_reset; /* Fallthrough */ case SND_PCM_STATE_XRUN: alsa_error("prepare", snd_pcm_prepare(alsa_hw.handle)); alsa_error("start", snd_pcm_start(alsa_hw.handle)); var_reset: /* Reset variables */ sample_count = 0; waiting_zerox = 0; signal_level = 0; signal_state = 0; signal_max = signal_min = 0x80; break; default: /* Stream is okay */ break; } /* Read all available data */ if ((count = snd_pcm_avail_update(alsa_hw.handle)) > 0) { if (count > (READ_BUFFER_SIZE / (bytes_per_sample * alsa_hw.num_channels))) count = READ_BUFFER_SIZE / (bytes_per_sample * alsa_hw.num_channels); count = snd_pcm_readi(alsa_hw.handle, buff, count); /*Loop around samples, if stereo we are *only interested in one channel*/ for (i = 0; i < count; i++) { /* cs == current sample */ unsigned char cs, as, sl, sz, xz; if (bytes_per_sample == 2) { cs = ((*(short *) &buff[i * bytes_per_sample * alsa_hw.num_channels + bytes_per_sample * alsa_hw.channel]) >> 8); cs ^= 0x80; } else { cs = buff[i]; /* Convert signed samples to unsigned */ if (alsa_hw.format == SND_PCM_FORMAT_S8) { cs ^= 0x80; } } /* Track signal middle value (it could differ from 0x80) */ sz = (signal_min + signal_max) / 2; if (cs <= sz) signal_min = (signal_min * 7 + cs) / 8; if (cs >= sz) signal_max = (signal_max * 7 + cs) / 8; /* Compute the absolute signal deviation from middle */ as = U8_ABSDIFF(cs, sz); /* Integrate incoming signal (auto level adjustment) */ signal_level = (signal_level * 7 + as) / 8; /* Don't let too low signal levels as it makes us sensible to noise */ sl = signal_level; if (sl < 16) sl = 16; /* Detect crossing current "zero" level */ xz = ((cs - sz) ^ (ps - sz)) & 0x80; /* Don't wait for zero crossing for too long */ if (waiting_zerox && !xz) waiting_zerox--; /* Detect significant signal level changes */ if ((abs(cs - ps) > sl / 2) && xz) waiting_zerox = 2; /* If we have crossed zero with a substantial level change, go */ if (waiting_zerox && xz) { lirc_t x; waiting_zerox = 0; if (sample_count >= maxcount) { x = PULSE_MASK; sample_count = 0; } else { /** * Try to interpolate the samples and determine where exactly * the zero crossing point was. This is required as the * remote signal frequency is relatively close to our sampling * frequency thus a sampling error of 1 sample can lead to * substantial time differences. * * slope = (x2 - x1) / (y2 - y1) * x = x1 + (y - y1) * slope * * where x1=-1, x2=0, y1=ps, y2=cs, y=sz, thus: * * x = -1 + (y - y1) / (y2 - y1), or * ==> x = (y - y2) / (y2 - y1) * * y2 (cs) cannot be equal to y1 (ps), otherwise we wouldn't * get here. */ int delta = (((int)sz - (int)cs) << 8) / ((int)cs - (int)ps); /* This expression can easily overflow the 'long' value since it * multiplies two 24.8 values (and we get a 24.16 instead). * To avoid this we cast the intermediate value to "long long". */ x = (((long long)sample_count + delta) * mulconst) >> 16; /* The rest of the quantum is on behalf of next pulse. Note that * sample_count can easily be assigned here a negative value (in * the case zero crossing occurs during the next quantum). */ sample_count = -delta; } /* Consider impossible pulses with length greater than * 0.02 seconds, thus it is a space (desynchronization). */ if ((x > 20000) && signal_state) { signal_state = 0; LOGPRINTF(1, "Pulse/space desynchronization fixed - len %u", x); } x |= signal_state; /* Write the LIRC code to the FIFO */ write(alsa_hw.fd, &x, sizeof(x)); signal_state ^= PULSE_BIT; }
/** * This method will read data from the given sound device into the buffer. * @param buffer This is a pointer to a buffer that is to be written into. The calee is responsible for providing this buffer. The buffer must be the isze calculated by the getRequiredBufferisze() method. * @return The return will be the number of bytes written into the buffer. */ int AudioInterface::read(char* buffer) { return snd_pcm_readi(handle, buffer, frames); }
int main(int argc, char *argv[]) { ros::init(argc, argv, "cmd_control"); ros::NodeHandle n; ros::Publisher motor_pub = n.advertise<std_msgs::Char>("motor_chatter", 1000); std::string port; ros::param::param<std::string>("~port", port, "/dev/ttyACM0"); int baud; ros::param::param<int>("~baud", baud, 57600); int byte_per_sample = bits_per_sample >> 3; long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; char *speechbuf; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, channels); /* 44100 bits/second sampling rate (CD quality) */ //val = 44100; val = sample_rate; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = frames_per_period; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * channels * byte_per_sample; /* 2 bytes/sample, 1 channels */ speechbuf = (char *) malloc(size); //printf("buffer size %d\n", size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); int client_sockfd; struct sockaddr_in remote_addr; //服务器端网络地址结构体 memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零 remote_addr.sin_family=AF_INET; //设置为IP通信 remote_addr.sin_addr.s_addr=inet_addr("10.0.1.0");//服务器IP地址 remote_addr.sin_port=htons(port); //服务器端口号 /*创建客户端套接字--IPv4协议,面向连接通信,TCP协议*/ if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0) { perror("socket failed\n"); return 1; } /*将套接字绑定到服务器的网络地址上*/ if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0) { perror("connect failed\n"); return 1; } printf("connected to server\n"); int len = 10 * FRAME_LEN; //printf("pcm size is %d", pcm_size); int totallen = 0; totallen = 0; int sendlen =0; int pcm_count = 0; int num = 0; pthread_t thread_recv; int err; void *tret; if((err = pthread_create(&thread_recv, NULL, &recv_cmd_func, &client_sockfd)) != 0) { printf("thread recv erro : %s \n", strerror(err)); return -1; } sleep(1); //printf("thread creat is\n" ); //fflush(stdout); while(1) { rc = snd_pcm_readi(handle, speechbuf, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); break; } sendlen = send(client_sockfd, speechbuf, len, 0); if(sendlen < 0) printf("send failed \n"); } if((err = pthread_join(thread_recv, &tret)) != 0) { printf("can not join thread_recv %s!\n", strerror(err)); exit(-1); } getchar(); close(client_sockfd); snd_pcm_drain(handle); snd_pcm_close(handle); free(speechbuf); return 0; }
void ALSAInput::InputThread() { try { Logger::LogInfo("[ALSAInput::InputThread] " + QObject::tr("Input thread started.")); std::vector<uint8_t> buffer(m_alsa_period_size * m_channels * 2); bool has_first_samples = false; int64_t first_timestamp = 0; // value won't be used, but GCC gives a warning otherwise while(!m_should_stop) { // wait until samples are available // This is not actually required since snd_pcm_readi is blocking, but unlike snd_pcm_read, // this function has a timeout value. This means the input thread won't hang if the device turns out to be dead. int res = snd_pcm_wait(m_alsa_pcm, 1000); if(res == 0) { continue; } if(res < 0) { if(res == -EPIPE) { ALSARecoverAfterOverrun(m_alsa_pcm); PushAudioHole(); } else { Logger::LogError("[ALSAInput::InputThread] " + QObject::tr("Error: Can't check whether samples are available!")); throw ALSAException(); } continue; } // read the samples snd_pcm_sframes_t samples_read = snd_pcm_readi(m_alsa_pcm, buffer.data(), m_alsa_period_size); if(samples_read < 0) { if(samples_read == -EPIPE) { ALSARecoverAfterOverrun(m_alsa_pcm); PushAudioHole(); } else { Logger::LogError("[ALSAInput::InputThread] " + QObject::tr("Error: Can't read samples!")); throw ALSAException(); } continue; } if(samples_read <= 0) continue; int64_t timestamp = hrt_time_micro(); // skip the first samples if(has_first_samples) { if(timestamp > first_timestamp + START_DELAY) { // push the samples int64_t time = timestamp - (int64_t) samples_read * (int64_t) 1000000 / (int64_t) m_sample_rate; PushAudioSamples(m_sample_rate, m_channels, samples_read, buffer.data(), AV_SAMPLE_FMT_S16, time); } } else { has_first_samples = true; first_timestamp = timestamp; } } Logger::LogInfo("[ALSAInput::InputThread] " + QObject::tr("Input thread stopped.")); } catch(const std::exception& e) { m_error_occurred = true; Logger::LogError("[ALSAInput::InputThread] " + QObject::tr("Exception '%1' in input thread.").arg(e.what())); } catch(...) { m_error_occurred = true; Logger::LogError("[ALSAInput::InputThread] " + QObject::tr("Unknown exception in input thread.")); } }
int main(int ac, char** av) { pcm_desc_t desc; pcm_handle_t ipcm; pcm_handle_t opcm; mod_handle_t mod; int err; cmdline_t cmd; size_t i; err = -1; if (get_cmdline(&cmd, ac - 1, av + 1)) goto on_error_0; pcm_init_desc(&desc); desc.flags |= PCM_FLAG_IN; if (cmd.flags & CMDLINE_FLAG(IPCM)) desc.name = cmd.ipcm; if (pcm_open(&ipcm, &desc)) goto on_error_0; pcm_init_desc(&desc); desc.flags |= PCM_FLAG_OUT; if (cmd.flags & CMDLINE_FLAG(OPCM)) desc.name = cmd.opcm; if (pcm_open(&opcm, &desc)) goto on_error_1; if (mod_open(&mod, 512)) goto on_error_2; if (pcm_start(&ipcm)) goto on_error_3; if (pcm_start(&opcm)) goto on_error_3; signal(SIGINT, on_sigint); for (i = 0; is_sigint == 0; i += 1) { size_t nsampl; size_t navail; size_t off; /* read ipcm */ err = snd_pcm_wait(ipcm.pcm, -1); if (is_sigint) break ; if (err < 0) goto on_ipcm_xrun; navail = (size_t)snd_pcm_avail_update(ipcm.pcm); if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.nsampl - ipcm.wpos; else nsampl = ipcm.rpos - ipcm.wpos; if (nsampl > navail) nsampl = navail; off = ipcm.wpos * ipcm.scale; err = snd_pcm_readi(ipcm.pcm, ipcm.buf + off, nsampl); if (err < 0) goto on_ipcm_xrun; ipcm.wpos += (size_t)err; if (ipcm.wpos == ipcm.nsampl) ipcm.wpos = 0; /* apply modifier */ redo_mod: if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.wpos - ipcm.rpos; else nsampl = ipcm.nsampl - ipcm.rpos + ipcm.wpos; if (cmd.flags & CMDLINE_FLAG(FILT)) { const size_t n = mod_apply (&mod, ipcm.buf, ipcm.nsampl, ipcm.rpos, nsampl); nsampl = n; } if (nsampl == 0) continue ; if ((ipcm.rpos + nsampl) > ipcm.nsampl) { const size_t n = ipcm.nsampl - ipcm.rpos; off = ipcm.rpos * ipcm.scale; err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, n); if (err < 0) goto on_opcm_xrun; nsampl -= n; ipcm.rpos = 0; } off = ipcm.rpos * ipcm.scale; err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, nsampl); if (err < 0) goto on_opcm_xrun; ipcm.rpos += nsampl; if (ipcm.rpos == ipcm.nsampl) ipcm.rpos = 0; goto redo_mod; continue ; on_ipcm_xrun: if (pcm_recover_xrun(&ipcm, err)) PERROR_GOTO("", on_error_2); continue ; on_opcm_xrun: if (pcm_recover_xrun(&opcm, err)) PERROR_GOTO("", on_error_2); continue ; } err = 0; on_error_3: mod_close(&mod); on_error_2: pcm_close(&opcm); on_error_1: pcm_close(&ipcm); on_error_0: return err; }
int main(int argc, char *argv[]) { int res, size; float *ibuff, *obuff; float shift; if (argc < 2) { print_usage(argv[0]); return 1; } shift = atof(argv[1]); if (shift < 0.5 || shift > 2.0) shift = 0.8; snd_pcm_uframes_t frames; frames = 1024; size = frames * 4; ibuff = malloc(size); obuff = malloc(size); res = snd_pcm_open(&pcm_c, name, SND_PCM_STREAM_CAPTURE, 0); if (res != 0) { printf("open for capture err\n"); exit(1); } res = snd_pcm_open(&pcm_p, name, SND_PCM_STREAM_PLAYBACK, 0); if (res != 0) { printf("open for playback err\n"); exit(1); } res = snd_pcm_set_params(pcm_p, SND_PCM_FORMAT_FLOAT_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 44100, 1, 100000); if (res != 0) { fprintf(stderr, "unable to set params(: %s\n", snd_strerror(res)); exit(1); } res = snd_pcm_set_params(pcm_c, SND_PCM_FORMAT_FLOAT_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 44100, 1, 0); if (res != 0) { fprintf(stderr, "unable to set params(: %s\n", snd_strerror(res)); exit(1); } snd_pcm_prepare(pcm_c); snd_pcm_prepare(pcm_p); while (1) { res = snd_pcm_readi(pcm_c, ibuff, frames); if (res == -EPIPE) { // EPIPE means overrun fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(pcm_c); } else if (res < 0) fprintf(stderr, "error from read: %s\n", snd_strerror(res)); else if (res != (int)frames) fprintf(stderr, "short read, read %d frames\n", res); pitch_shift(shift, frames, 512, 1, 44100, ibuff, obuff); res = snd_pcm_writei(pcm_p, obuff, frames); //write(1, obuff, frames * sizeof(float)); if (res == -EPIPE) { // EPIPE means underrun fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(pcm_p); } else if (res < 0) fprintf(stderr, "error from writei: %s\n", snd_strerror(res)); else if (res != (int)frames) fprintf(stderr, "short write, write %d frames\n", res); } snd_pcm_drain(pcm_c); snd_pcm_drain(pcm_p); snd_pcm_close(pcm_c); snd_pcm_close(pcm_p); free(ibuff); free(obuff); return 0; }
main (int argc, char *argv[]) { int i; int err; short buf[128]; snd_pcm_t *capture_handle; snd_pcm_hw_params_t *hw_params; if ((err = snd_pcm_open (&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", argv[1], snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, 44100, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); exit (1); } snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_prepare (capture_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } for (i = 0; i < 10; ++i) { if ((err = snd_pcm_readi (capture_handle, buf, 128)) != 128) { fprintf (stderr, "read from audio interface failed (%s)\n", snd_strerror (err)); exit (1); } } snd_pcm_close (capture_handle); exit (0); }
void audiosource_alsa::loop_async_thread_rec() { config* cfg = config::Instance(); std::vector<short> buffer; std::vector<float> bufferf; snd_pcm_sframes_t frames; int ret; int buf_size = (cfg->frames_per_buff() > 0) ? cfg->frames_per_buff() : (get_sample_rate()); bool restart = true; buffer.resize(buf_size); bufferf.resize(buf_size); if ((ret = snd_pcm_prepare(c_handle_)) < 0) { std::cerr << "snd_pcm_prepare capture error: " << snd_strerror(ret) << std::endl; close(); return; } /* FIXME Break the loop */ for (;;) { if (restart) { if (cfg->debug()) { std::cerr << "ALSA restart" << std::endl; } restart = false; snd_pcm_drop(c_handle_); snd_pcm_prepare(c_handle_); } /* Read data from the soundcard */ for (;;) { frames = snd_pcm_readi(c_handle_, buffer.data(), buffer.size()); if (frames == -EAGAIN) { if (cfg->debug()) { std::cerr << "ALSA EAGAIN" << std::endl; } continue; } else { if (frames < 0) { if (cfg->debug()) { std::cerr << "ALSA snd_pcm_readi < 0 = " << frames << std::endl; } restart = true; } break; } } if (restart) { continue; } if (cfg->debug() && frames != (snd_pcm_sframes_t)buffer.size()) { std::cerr << "ALSA short read, expected " << buffer.size() << " wrote " << frames << std::endl; } for (int i = 0; i < frames; ++i) { bufferf[i] = buffer[i] * 1.0 / 32768.0f; } get_listener()->input_callback(this, bufferf.data(), frames); } }
void AudioALSA::proc_audio() { int i,j,n,trig,trigpos; int err = 0; static int k = 0; unsigned char *c = NULL; double ldf,mldf; processing_audio = 1; trigpos = 0; c = sample; if ((err = snd_pcm_readi(capture_handle, c, blksize)) != blksize) { std::cerr << "read from audio interface failed (" << snd_strerror(err) << ")." << std::endl; exit (1); } n = blksize; // We search a 0 crossing value (beware: unsigned char !) for(i=0; i<n && Abs(c[i]-128)<2; i++); j = 0; trig = 0; if (i<n) do { for( ; i<n-1; i++) /* n-1 because of POSTRIG uses i+1 */ if (POSTRIG(c,i)) { trig = 1; trigpos = i; } if (trig==0) { if ((err = snd_pcm_readi(capture_handle, c, blksize)) != blksize) { std::cerr << "read from audio interface failed (" << snd_strerror(err) << ")." << std::endl; exit (1); } n = blksize; j++; i=0; } // We loop over the samples until we have found a new 0 crossing value } while((!trig) && j<NO_TRIG_LIMIT); if (trig) { for(i=n-trigpos; i<sampnr; i+=n) { c += n; if ((err = snd_pcm_readi(capture_handle, c, blksize)) != blksize) { std::cerr << "read from audio interface failed (" << snd_strerror(err) << ")." << std::endl; exit (1); } n = blksize; } // Plot the measured values mw->getOsziPtr()->setSamplePtr(&sample[trigpos]); mw->getOsziPtr()->paintSample(); freq_0t = (double)sampfreq * mw->getOsziPtr()->getfreq2(); lfreq_0t = log(freq_0t); while(lfreq_0t < lfreqs[0] - D_NOTE_LOG/2.0) lfreq_0t += LOG_2; while(lfreq_0t >= lfreqs[0] + LOG_2 - D_NOTE_LOG/2.0) lfreq_0t -= LOG_2; mldf = D_NOTE_LOG; note_0t = 0; for(i=0; i<12; i++) { ldf = fabs(lfreq_0t - lfreqs[i]); if (ldf < mldf) { mldf = ldf; note_0t = i; } } // Display the frequency update_lfreq(); double nfreq_0t = freqs[note_0t]; while(nfreq_0t/freq_0t > D_NOTE_SQRT) nfreq_0t /= 2.0; while(freq_0t/nfreq_0t > D_NOTE_SQRT) nfreq_0t *= 2.0; // Display the note update_nfreq(nfreq_0t); } k++; processing_audio = 0; }
static void * audio_thread(void *param) { struct pollfd *fds = NULL; nfds_t nfds = 0; static char buf[16 * 1024]; ppb_message_loop_mark_thread_unsuitable(); nfds = do_rebuild_fds(&fds); pthread_barrier_wait(&stream_list_update_barrier); if (nfds == 0) goto quit; while (1) { if (g_atomic_int_get(&terminate_thread)) goto quit; int res = poll(fds, nfds, 10 * 1000); if (res == -1) { if (errno == EINTR) continue; trace_error("%s, poll, errno=%d\n", __func__, errno); continue; } if (res == 0 || fds == NULL) continue; if (fds[0].revents) drain_wakeup_pipe(fds[0].fd); if (g_atomic_int_get(&rebuild_fds)) { nfds = do_rebuild_fds(&fds); pthread_barrier_wait(&stream_list_update_barrier); if (nfds == 0) goto quit; } for (uintptr_t k = 1; k < nfds; k ++) { unsigned short revents = 0; audio_stream *as = g_hash_table_lookup(stream_by_fd_ht, GINT_TO_POINTER(fds[k].fd)); // check if stream was deleted if (!as) continue; snd_pcm_poll_descriptors_revents(as->pcm, &fds[k], 1, &revents); if (revents & (~(POLLIN | POLLOUT))) { trace_warning("%s, revents have unexpected flags set (%u)\n", __func__, (unsigned int)revents); recover_pcm(as->pcm); } if (revents & (POLLIN | POLLOUT)) { int paused = g_atomic_int_get(&as->paused); snd_pcm_sframes_t frame_count = snd_pcm_avail(as->pcm); if (revents & POLLIN) { // POLLIN const size_t frame_size = 1 * sizeof(int16_t); // mono 16-bit const size_t max_segment_length = MIN(as->sample_frame_count * frame_size, sizeof(buf)); size_t to_process = frame_count * frame_size; while (to_process > 0) { snd_pcm_sframes_t frames_read; const size_t segment_length = MIN(to_process, max_segment_length); frames_read = snd_pcm_readi(as->pcm, buf, segment_length / frame_size); if (frames_read < 0) { trace_warning("%s, snd_pcm_readi error %d\n", __func__, (int)frames_read); recover_pcm(as->pcm); continue; } if (!paused && as->capture_cb) as->capture_cb(buf, frames_read * frame_size, 0, as->cb_user_data); to_process -= frames_read * frame_size; } } else { // POLLOUT const size_t frame_size = 2 * sizeof(int16_t); // stereo 16-bit const size_t max_segment_length = MIN(as->sample_frame_count * frame_size, sizeof(buf)); size_t to_process = frame_count * frame_size; while (to_process > 0) { snd_pcm_sframes_t frames_written; const size_t segment_length = MIN(to_process, max_segment_length); if (paused || !as->playback_cb) memset(buf, 0, segment_length); else as->playback_cb(buf, segment_length, 0, as->cb_user_data); frames_written = snd_pcm_writei(as->pcm, buf, segment_length / frame_size); if (frames_written < 0) { trace_warning("%s, snd_pcm_writei error %d\n", __func__, (int)frames_written); recover_pcm(as->pcm); continue; } to_process -= frames_written * frame_size; } } } } } quit: free(fds); return NULL; }