📄 audio.c
字号:
/* * audio.c * * ============================================================================ * Copyright (c) Texas Instruments Inc 2005 * * Use of this software is controlled by the terms and conditions found in the * license agreement under which this software has been supplied or provided. * ============================================================================ *//* Standard Linux headers */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <fcntl.h>#include <errno.h>#include <linux/soundcard.h>/* Codec Engine headers */#include <xdc/std.h>#include <ti/sdo/ce/Engine.h>#include <ti/sdo/ce/osal/Memory.h>#include <ti/sdo/ce/audio/auddec.h>/* Demo headers */#include <rendezvous.h>#include "decode.h"#include "audio.h"#include "loader.h"/* The max amount of bytes of audio data to process at once */#define SOUNDBLKSIZE 2 * 1024/* The maximum size of the raw decoded samples */ #define RAWBUFSIZE SOUNDBLKSIZE * 5/* The size of the read buffer */#define READBUFSIZE 60 * 1024/* The number of channels of the audio codec */#define NUM_CHANNELS 2/* The sample rate of the audio codec */#define SAMPLE_RATE 44100/* The gain (0-100) of the left and right channels */#define LEFT_GAIN 100#define RIGHT_GAIN 100/* The levels of initialization */#define AUDIOFILEINITIALIZED 0x1#define SOUNDDEVICEINITIALIZED 0x2#define ENGINEOPENED 0x4#define AUDIODECODERCREATED 0x8#define READBUFFERALLOCATED 0x10#define RAWBUFFERALLOCATED 0x20/* Video decoder names */char *audioDecodeAlgNames[NUM_AUDIO_DECODERS] = { "aacdec", "mp3dec"};/* Local function prototypes */static int audioDecodeAlgCreate(Engine_Handle hEngine, AUDDEC_Handle *hDecodePtr, enum AudioDecoder audioDecoder);static int decodeAudioBuffer(AUDDEC_Handle hDecode, char *inBuf, int inBufSize, char *outBuf, int *outBufSize, int *bytesProcessed, int *framesRejectedPtr);static int setSampleRate(int soundFd, int sampleRate);static int initSoundDevice(void);/****************************************************************************** * audioDecodeAlgCreate ******************************************************************************/static int audioDecodeAlgCreate(Engine_Handle hEngine, AUDDEC_Handle *hDecodePtr, enum AudioDecoder audioDecoder){ AUDDEC_DynamicParams dynamicParams; AUDDEC_Params params; AUDDEC_Status decStatus; XDAS_Int32 status; char *algName; AUDDEC_Handle hDecode; algName = audioDecodeAlgNames[audioDecoder]; params.size = sizeof(AUDDEC_Params); params.maxSampleRate = 48000; params.maxBitrate = 448000; params.maxNoOfCh = IAUDIO_STEREO; params.dataEndianness = XDM_BYTE; /* Create audio decoder */ hDecode = AUDDEC_create(hEngine, algName, ¶ms); if (hDecode == NULL) { ERR("Can't open audio decode algorithm\n"); return FAILURE; } /* Reset codec */ decStatus.size = sizeof(AUDDEC_Status); dynamicParams.size = sizeof(AUDDEC_DynamicParams); status = AUDDEC_control(hDecode, XDM_RESET, &dynamicParams, &decStatus); if (status != AUDDEC_EOK) { ERR("XDM_RESET failed, status=%ld\n", status); return FAILURE; } /* Set default dynamic parameters */ decStatus.size = sizeof(AUDDEC_Status); dynamicParams.size = sizeof(AUDDEC_DynamicParams); status = AUDDEC_control(hDecode, XDM_SETDEFAULT, &dynamicParams, &decStatus); if (status != AUDDEC_EOK) { ERR("XDM_SETDEFAULT failed, status=%ld\n", status); return FAILURE; } /* Set dynamic parameters */ decStatus.size = sizeof(AUDDEC_Status); dynamicParams.size = sizeof(AUDDEC_DynamicParams); dynamicParams.outputFormat = IAUDIO_INTERLEAVED; status = AUDDEC_control(hDecode, XDM_SETPARAMS, &dynamicParams, &decStatus); if (status != AUDDEC_EOK) { ERR("XDM_SETPARAMS failed, status=%ld\n", status); return FAILURE; } *hDecodePtr = hDecode; return SUCCESS;}/****************************************************************************** * decodeAudioBuffer ******************************************************************************/static int decodeAudioBuffer(AUDDEC_Handle hDecode, char *inBuf, int inBufSize, char *outBuf, int *outBufSize, int *bytesProcessed, int *framesRejectedPtr){ static int sampleRateInitialized = FALSE; AUDDEC_DynamicParams dynamicParams; XDAS_Int32 inBufSizeArray[1]; XDAS_Int32 outBufSizeArray[1]; XDM_BufDesc inBufDesc; XDM_BufDesc outBufDesc; XDAS_Int32 status; AUDDEC_InArgs inArgs; AUDDEC_OutArgs outArgs; AUDDEC_Status decStatus; inBufSizeArray[0] = inBufSize; outBufSizeArray[0] = RAWBUFSIZE; inBufDesc.bufSizes = inBufSizeArray; inBufDesc.bufs = (XDAS_Int8 **) &inBuf; inBufDesc.numBufs = 1; outBufDesc.bufSizes = outBufSizeArray; outBufDesc.bufs = (XDAS_Int8 **) &outBuf; outBufDesc.numBufs = 1; inArgs.size = sizeof(AUDDEC_InArgs); inArgs.numBytes = inBufSize; outArgs.size = sizeof(AUDDEC_OutArgs); /* Decode the audio buffer */ status = AUDDEC_process(hDecode, &inBufDesc, &outBufDesc, &inArgs, &outArgs); *bytesProcessed = outArgs.bytesConsumed; if (status != AUDDEC_EOK) { if (status == AUDDEC_ERUNTIME || outArgs.bytesConsumed == 0 || XDM_ISFATALERROR(outArgs.extendedError)) { ERR("AUDDEC_process() failed with a fatal error (%ld ext: %#lx\n", status, outArgs.extendedError); return FAILURE; } else { /* Make sure we don't output the corrupt samples */ *outBufSize = 0; (*framesRejectedPtr)++; return SUCCESS; } } /* Get the dynamic codec status */ decStatus.size = sizeof(AUDDEC_Status); dynamicParams.size = sizeof(AUDDEC_DynamicParams); status = AUDDEC_control(hDecode, XDM_GETSTATUS, &dynamicParams, &decStatus); if (status != AUDDEC_EOK) { ERR("XDM_GETSTATUS failed, status=%ld\n", status); return FAILURE; } /* Detect which sample rate was really used to encode the data */ if (!sampleRateInitialized) { if (setSampleRate(0, decStatus.sampleRate) == FAILURE) { return FAILURE; } gblSetSamplingFrequency(decStatus.sampleRate); sampleRateInitialized = TRUE; } *outBufSize = decStatus.frameLen * 4; *bytesProcessed = outArgs.bytesConsumed; return SUCCESS;}/****************************************************************************** * setSampleRate ******************************************************************************/static int setSampleRate(int soundFd, int sampleRate){ static int fd = 0; if (!fd) { if (!soundFd) { ERR("No valid sound filedescriptor available\n"); return FAILURE; } fd = soundFd; } /* Set the sample rate */ if (ioctl(fd, SNDCTL_DSP_SPEED, &sampleRate) == -1) { ERR("Could not set sample rate (%d)\n", sampleRate); return FAILURE; } return SUCCESS;}/****************************************************************************** * initSoundDevice ******************************************************************************/static int initSoundDevice(void){ int channels = NUM_CHANNELS; int format = AFMT_S16_LE; int soundFd; /* Open the sound device for writing */ soundFd = open(SOUND_DEVICE, O_WRONLY); if (soundFd == -1) { ERR("Failed to open the sound device (%s)\n", SOUND_DEVICE); return FAILURE; } /* Set the sound format (only AFMT_S16_LE supported) */ if (ioctl(soundFd, SNDCTL_DSP_SETFMT, &format) == -1) { ERR("Could not set format %d\n", format); return FAILURE; } /* Set the number of channels */ if (ioctl(soundFd, SNDCTL_DSP_CHANNELS, &channels) == -1) { ERR("Could not set mixer to %d channels\n", channels); return FAILURE; } /* Set the sample rate */ if (setSampleRate(soundFd, SAMPLE_RATE) == FAILURE) { return FAILURE; } return soundFd;}/****************************************************************************** * audioThrFxn ******************************************************************************/void *audioThrFxn(void *arg){ Engine_Handle hEngine = NULL; unsigned int initMask = 0; AudioEnv *envp = (AudioEnv *) arg; void *status = THREAD_SUCCESS; char *rawBuffer = NULL; int framesRejected = 0; int frameSize = 0; int outputFd = 0; AUDDEC_Handle hDecode; char *framePtr; int rawBufferSize; LoaderState lState; /* Initialize loader state */ lState.loop = envp->loop; lState.readBufSize = READBUFSIZE; lState.readSize = SOUNDBLKSIZE; lState.doneMask = SOUND_DONE; /* Open the audio file */ lState.inputFd = open(envp->audioFile, O_RDONLY); if (lState.inputFd == -1) { ERR("Failed to open %s (%s)\n", envp->audioFile, strerror(errno)); cleanup(THREAD_FAILURE); } DBG("Audio file successfully opened\n"); initMask |= AUDIOFILEINITIALIZED; /* Initialize the AIC33 audio codec for writing */ outputFd = initSoundDevice(); if (outputFd == FAILURE) { cleanup(THREAD_FAILURE); } DBG("Sound device initialized\n"); initMask |= SOUNDDEVICEINITIALIZED; /* Reset, load, and start DSP Engine */ hEngine = Engine_open(ENGINE_NAME, NULL, NULL); if (hEngine == NULL) { ERR("Failed to open codec engine %s\n", ENGINE_NAME); cleanup(THREAD_FAILURE); } DBG("Codec Engine opened in audio thread\n"); initMask |= ENGINEOPENED; /* Allocate and initialize audio decoder on the engine */ if (audioDecodeAlgCreate(hEngine, &hDecode, envp->audioDecoder) == FAILURE) { cleanup(THREAD_FAILURE); } DBG("Audio decoder created\n"); initMask |= AUDIODECODERCREATED; /* Allocate intermediate buffer (for encoded data) */ lState.readBuffer = (char *) Memory_contigAlloc(lState.readBufSize, Memory_DEFAULTALIGNMENT); if (lState.readBuffer == NULL) { ERR("Failed to allocate contiguous memory block.\n"); cleanup(THREAD_FAILURE); } DBG("Contiguous buffer allocated with physical address %#lx\n", Memory_getPhysicalAddress(lState.readBuffer)); initMask |= READBUFFERALLOCATED; /* Allocate buffer for raw data */ rawBuffer = (char *) Memory_contigAlloc(RAWBUFSIZE, Memory_DEFAULTALIGNMENT); if (rawBuffer == NULL) { ERR("Failed to allocate contiguous memory block.\n"); cleanup(THREAD_FAILURE); } DBG("Contiguous buffer allocated with physical address %#lx\n", Memory_getPhysicalAddress(rawBuffer)); initMask |= RAWBUFFERALLOCATED; /* Signal that initialization is done and wait for other threads */ Rendezvous_meet(envp->hRendezvous); /* Prime the file loader */ if (loaderPrime(&lState, &framePtr) == FAILURE) { cleanup(THREAD_FAILURE); } DBG("Entering audio main loop.\n"); while (!gblGetQuit()) { if (!gblGetPlay()) { usleep(PAUSE); continue; } /* Decode the encoded frame to the raw buffer */ if (decodeAudioBuffer(hDecode, framePtr, lState.readSize, rawBuffer, &rawBufferSize, &frameSize, &framesRejected) == FAILURE) { breakLoop(THREAD_FAILURE); } /* Write samples to the device driver from contiguous buffer */ if (write(outputFd, rawBuffer, rawBufferSize) == -1) { ERR("Error writing data to %s (%s)\n", SOUND_DEVICE, strerror(errno)); breakLoop(THREAD_FAILURE); } /* Read a new frame of encoded data from disk */ if (loaderGetFrame(&lState, frameSize, &framePtr) == FAILURE) { breakLoop(THREAD_FAILURE); } if (lState.endClip) { /* Recreate the algorithm */ AUDDEC_delete(hDecode); if (audioDecodeAlgCreate(hEngine, &hDecode, envp->audioDecoder) == FAILURE) { breakLoop(THREAD_FAILURE); } /* Prime the file loader */ if (loaderPrime(&lState, &framePtr) == FAILURE) { breakLoop(THREAD_FAILURE); } } /* Increment statistics for OSD display */ gblIncSoundBytesEncoded(frameSize); } printf("\nTotal number of audio frames rejected: %d\n", framesRejected);cleanup: /* Make sure the other threads aren't waiting for init to complete */ Rendezvous_force(envp->hRendezvous); /* Clean up the audio thread */ if (initMask & RAWBUFFERALLOCATED) { Memory_contigFree(rawBuffer, RAWBUFSIZE); } if (initMask & READBUFFERALLOCATED) { Memory_contigFree(lState.readBuffer, lState.readBufSize); } if (initMask & AUDIODECODERCREATED) { AUDDEC_delete(hDecode); } if (initMask & ENGINEOPENED) { Engine_close(hEngine); } if (initMask & SOUNDDEVICEINITIALIZED) { close(outputFd); } if (initMask & AUDIOFILEINITIALIZED) { close(lState.inputFd); } return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -