Esempio n. 1
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_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;
}
Esempio n. 2
0
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(&params);

	/* 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* [email protected] 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));
}
Esempio n. 4
0
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(&params);
    /* 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;

}
Esempio n. 5
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;
}
Esempio n. 6
0
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;
}
Esempio n. 8
0
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;
	}
Esempio n. 9
0
/*
 * 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;
}
Esempio n. 10
0
/*****************************************************************************
 * 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;
}
Esempio n. 11
0
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(&params);

    /* 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;
}
Esempio n. 12
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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(&params);

  /* 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;
}
Esempio n. 16
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(&params);
  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);
}
Esempio n. 17
0
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(&params);
	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++;
						}
					}
					
						
				
			}
Esempio n. 18
0
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);
  }
}
Esempio n. 20
0
File: mic.c Progetto: naeems/bkvoice
//音频采集线程
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(&params);/* 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;
}
Esempio n. 21
0
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;
			}
Esempio n. 22
0
/**
 * 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);
}
Esempio n. 23
0
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(&params);

	/* 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;
}
Esempio n. 24
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."));
	}
}
Esempio n. 25
0
File: main.c Progetto: texane/aspect
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;
}
Esempio n. 26
0
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;
}
Esempio n. 27
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);
	}
Esempio n. 28
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);
	}
}
Esempio n. 29
0
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;
}