?? audio_thread.c
字號:
/* Standard Linux headers */#include <stdio.h> // always include stdio.h#include <stdlib.h> // always include stdlib.h#include <fcntl.h> // defines open, read, write methods#include <unistd.h> // defines close and sleep methods#include <sys/ioctl.h> // defines driver ioctl method#include <linux/soundcard.h> // defines OSS driver functions#include <string.h> // defines memcpy/* Codec Engine headers */#include <xdc/std.h> // xdc base definitions. Must come 1st#include <ti/sdo/ce/Engine.h> // required for any CE application#include <ti/sdo/ce/audio/auddec.h> // defines audio encoder methods#include <ti/sdo/ce/audio/audenc.h> // defines audio decoder methods/* Application headers */#include "debug.h" // DBG and ERR macros#include "audio_thread.h" // audio thread definitions#include "audio_input_output.h" // audio driver input and output functions#include "engine.h" // Helper utilities for engine_open and close#include "audio_encoder.h" // audio encoder functions#include "audio_decoder.h" // audio decoder functions/* OSS and Mixer devices */#define SOUND_DEVICE "/dev/dsp"#define MIXER_DEVICE "/dev/mixer"/* Audio encoder and decoder names */#define AUDIO_DECODER "audio_decoder"#define AUDIO_ENCODER "audio_encoder"/* The sample rate of the audio codec.*/#define SAMPLE_RATE 44100/* The gain (0-100) of the left channel.*/#define LEFT_GAIN 100/* The gain (0-100) of the right channel.*/#define RIGHT_GAIN 100/* Parameters for audio thread execution */#define BLOCKSIZE 44100/****************************************************************************** * 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){/* 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_OSS_INITIALIZED 0x1#define INPUT_BUFFER_ALLOCATED 0x2#define OUTPUT_OSS_INITIALIZED 0x4#define OUTPUT_BUFFER_ALLOCATED 0x8#define AUDIOENCODERCREATED 0x10#define AUDIODECODERCREATED 0x20#define ENCODEDBUFFERALLOCATED 0x40#define ENGINEOPENED 0x80 unsigned int initMask = 0x0;// used to only cleanup items that were init'ed/* Input and output driver variables */ int inputFd = 0; // input driver file descriptor (i.e. handle) int outputFd = 0; // output driver file descriptor (i.e. handle) int blksize = BLOCKSIZE;// raw input or output frame size char *inputBuffer = NULL; // input buffer for driver to read into char *outputBuffer = NULL;// output buffer for driver to read from int vol = LEFT_GAIN | (RIGHT_GAIN << 8); // volume setting int i; // loop counter to initialize output buffer/* Intermediate buffer for encoded audio */ char *encodedBuffer = NULL; // pointer to encoded buffer int encodedSize = 0; // size of encoded buffer (numbytes specifies // how full it is, numbytes < encodedSize) int numbytes; // number of bytes in an encoded frame/* Codec engine variables */ Engine_Handle engineHandle = NULL; // handle to the engine AUDENC_Handle encoderHandle = NULL; // handle to audio encoder AUDDEC_Handle decoderHandle = NULL; // handle to audio decoder /* Thread Create Phase -- secure and initialize resources */ /* Open an OSS device channel for audio input */ if(audio_input_setup(&inputFd, SOUND_DEVICE, MIXER_DEVICE, SOUND_MASK_LINE, vol, SAMPLE_RATE, &blksize) == AUDIO_FAILURE){ ERR("audio_input_setup failed in audio_thread_fxn\n\n"); status = AUDIO_THREAD_FAILURE; goto cleanup; } /* Record that input OSS device was opened in initialization bitmask */ initMask |= INPUT_OSS_INITIALIZED; /* Create output buffer to write from into OSS output 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 output buffer was allocated in initialization bitmask */ initMask |= INPUT_BUFFER_ALLOCATED; /* open the codec engine */ /* note: codec engine should be opened in each thread that uses it */ if(engine_setup(&engineHandle,envPtr->engineName,NULL) != ENGINE_SUCCESS){ ERR("engine_setup failed in audio_thread_fxn\n"); status = AUDIO_THREAD_FAILURE; goto cleanup; } /* Allocate and initialize audio encoder on the engine */ /* uses engineHandle global variable assumed set before entry */ if(audio_encoder_setup(engineHandle, AUDIO_ENCODER, &encoderHandle) == AENC_FAILURE) { ERR("audio_encoder_setup failed in audio_thread_fxn\n"); status = AUDIO_THREAD_FAILURE; goto cleanup; } initMask |= AUDIOENCODERCREATED; /* Allocate and initialize audio decoder on the engine */ if(audio_decoder_setup(engineHandle, AUDIO_DECODER, &decoderHandle) == ADEC_FAILURE) { ERR("audio_decoder_setup failed in audio_thread_fxn\n"); status = AUDIO_THREAD_FAILURE; goto cleanup; } initMask |= AUDIODECODERCREATED; /* Initialize the output OSS device */ if(audio_output_setup(&outputFd, SOUND_DEVICE, SAMPLE_RATE) == AUDIO_FAILURE){ ERR("audio_output_setup failed in audio_thread_fxn\n"); status = AUDIO_THREAD_FAILURE; goto cleanup; } /* Record that input OSS device was opened in initialization bitmask */ initMask |= OUTPUT_OSS_INITIALIZED; /* Create output buffer to write from into OSS output device */ if((outputBuffer = malloc(blksize)) == NULL) { ERR("Failed to allocate memory for output block (%d)\n", blksize); status = AUDIO_THREAD_FAILURE; goto cleanup; } DBG("Allocated output audio buffer of size %d to address %p\n", blksize, outputBuffer); /* Record that the output buffer was allocated in initialization bitmask */ initMask |= OUTPUT_BUFFER_ALLOCATED; /* Create encoded buffer to store encoded audio */ /* If copy codec is used, encoded buffer is the same size as raw buffer */ /* and real codecs will have smaller encoded sizes than this */ encodedSize = blksize; if ((encodedBuffer = malloc(encodedSize)) == NULL) { ERR("Failed to allocate memory for output block (%d)\n", blksize); status = AUDIO_THREAD_FAILURE; goto cleanup; } initMask |= ENCODEDBUFFERALLOCATED; DBG("Allocated intermediate audio buffer of size %d\n", blksize); DBG("\tto address %p\n", encodedBuffer); /* Write two buffers into OSS output device for some room to work */ /* once the driver begins output, a starvation condition */ /* will lock the driver up!!! */ for (i=0; i<blksize; i++){ outputBuffer[i] = 0; } if (write(outputFd, outputBuffer, blksize) == -1) { ERR("Error writing the data to file descriptor %d\n", outputFd); status = AUDIO_THREAD_FAILURE; goto cleanup; } if (write(outputFd, outputBuffer, blksize) == -1) { ERR("Error writing the data to file descriptor %d\n", outputFd); status = AUDIO_THREAD_FAILURE; goto cleanup; } /* Thread Execute Phase -- perform I/O and processing */ DBG("Entering audio_thread_fxn processing loop\n"); while (!envPtr->quit){ /* Reverb variables */ short *shBufPtr = NULL; // Audio data is 16-bit, so helps to recast short *shRevPtr = NULL; // Audio data is 16-bit, so helps to recast#define REVERB_SIZE 11024#define REV_FACTOR 0.5 /* REVERB_SIZE must be >= blksize (3072) and even */ /* REVERB_SIZE of 5512-11024, REV_FACTOR 0.5 tends to thicken music */ /* REVERB_SIZE of 44100, REV_FACTOR 0.8 tends to make your music */ /* sound like the theme to "halloween" */ char reverbBuffer[REVERB_SIZE];// Previous data for reverb /* Read input buffer from OSS input device */ if ((int) read(inputFd, inputBuffer, blksize) < blksize) { ERR("Error reading the data from file descriptor %d\n", inputFd); status = AUDIO_THREAD_FAILURE; goto cleanup; } /* Set short pointers to buffer locations */ shBufPtr = (short *) inputBuffer; shRevPtr = (short *) reverbBuffer; /* Multiply delayed values by REV_FACTOR and add into input stream */ /* Divide by 1+REV_FACTOR to maintain gain of 1 */ for(i=0;i<(blksize>>1);i++){ shBufPtr[i] = (int)((float)shBufPtr[i] / (float)(1.0 +REV_FACTOR)); shBufPtr[i] += (int)((float)shRevPtr[i]*(float)REV_FACTOR / (float)(1.0 +REV_FACTOR)); } /* Maintain the delay line by moving old values down and adding */ /* input buffer to the top. Note, this code assumes that */ /* REVERB_SIZE > blksize, otherwise, it will break! */ memcpy(reverbBuffer, reverbBuffer + blksize, REVERB_SIZE - blksize); memcpy(reverbBuffer + REVERB_SIZE - blksize, inputBuffer, blksize); /* On input to encode_audio, this value is size of encodedBuffer */ numbytes = encodedSize; /* Encode the buffer */ if (encode_audio(encoderHandle, inputBuffer, blksize, encodedBuffer, &numbytes) == AENC_FAILURE) { ERR("Error encoding audio data (encoder handle %p)\n", encoderHandle); status = AUDIO_THREAD_FAILURE; break; } /* Decode the buffer */ if (decode_audio(decoderHandle, encodedBuffer, numbytes, outputBuffer, blksize) == ADEC_FAILURE) { ERR("Error decoding audio data (decoder handle %p)\n", decoderHandle); status = AUDIO_THREAD_FAILURE; break; } /* Write output buffer into OSS output device */ if (write(outputFd, outputBuffer, blksize) == -1) { ERR("Error writing the data to file descriptor %d\n", outputFd); status = AUDIO_THREAD_FAILURE; goto cleanup; } }cleanup: DBG("Exited audio_thread_fxn processing loop\n"); DBG("Starting audio thread cleanup to return resources to system\n"); /* Thread Delete Phase -- clean up resources used */ /* Use the initMask to only free resources that were allocated */ /* Nothing to be done for mixer device, it was closed after init */ /* Note the OSS output device must be closed before anything else */ /* if this driver expends it's backlog of data before it is */ /* closed, it will lock up the application. */ /* Close output OSS device */ if(initMask & OUTPUT_OSS_INITIALIZED) if(audio_output_cleanup(outputFd) != AUDIO_SUCCESS) { ERR("audio_output_cleanup failed for file descriptor %d\n", outputFd); status = AUDIO_THREAD_FAILURE; } /* Free output buffer */ if(initMask & OUTPUT_BUFFER_ALLOCATED){ DBG("Freed audio output buffer at location %p\n", outputBuffer); free(outputBuffer); } /* Close input OSS device */ if(initMask & INPUT_OSS_INITIALIZED) if(audio_input_cleanup(inputFd) != AUDIO_SUCCESS) { ERR("audio_output_cleanup failed for file descriptor %d\n", inputFd); status = AUDIO_THREAD_FAILURE; } /* Delete audio decoder */ if (initMask & AUDIODECODERCREATED) if( audio_decoder_cleanup(decoderHandle) != ADEC_SUCCESS ) { ERR("audio_decoder_cleanup failed\n"); status = AUDIO_THREAD_FAILURE; } /* Delete audio encoder */ if (initMask & AUDIOENCODERCREATED) if( audio_encoder_cleanup(encoderHandle) != AENC_SUCCESS ) { ERR("audio_encoder_cleanup failed\n"); status = AUDIO_THREAD_FAILURE; } /* Close the engine */ if (initMask & ENGINEOPENED){ engine_cleanup(engineHandle); } /* Free input buffer */ if(initMask & INPUT_BUFFER_ALLOCATED){ DBG("Freed audio input buffer at location %p\n", inputBuffer); free(inputBuffer); } /* Free intermediate (encoded) buffer */ if (initMask & ENCODEDBUFFERALLOCATED) { DBG("Freed intermediate audio buffer at %p\n", encodedBuffer); free(encodedBuffer); } /* Return the status of the thread execution */ DBG("Audio thread cleanup complete. Exiting audio_thread_fxn\n"); return status;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -