Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <unistd.h>
- #include <semaphore.h>
- #include <libmodplug/modplug.h>
- #include "bcm_host.h"
- #include "ilclient.h"
- #include "HybridSong.xm.h"
- #ifndef countof
- #define countof(arr) (sizeof(arr) / sizeof(arr[0]))
- #endif
- //#define BUFFER_SIZE_SAMPLES 1024
- #define BUFFER_SIZE_SAMPLES 512*1024
- typedef int int32_t;
- typedef struct {
- sem_t sema;
- ILCLIENT_T *client;
- COMPONENT_T *audio_render;
- COMPONENT_T *list[2];
- OMX_BUFFERHEADERTYPE *user_buffer_list; // buffers owned by the client
- uint32_t num_buffers;
- uint32_t bytes_per_sample;
- } AUDIOPLAY_STATE_T;
- static void input_buffer_callback(void *data, COMPONENT_T *comp)
- {
- // do nothing - could add a callback to the user
- // to indicate more buffers may be available.
- }
- int32_t audioplay_create(AUDIOPLAY_STATE_T **handle,
- uint32_t sample_rate,
- uint32_t num_channels,
- uint32_t bit_depth,
- uint32_t num_buffers,
- uint32_t buffer_size)
- {
- uint32_t bytes_per_sample = (bit_depth * num_channels) >> 3;
- int32_t ret = -1;
- *handle = NULL;
- // basic sanity check on arguments
- if(sample_rate >= 8000 && sample_rate <= 96000 &&
- (num_channels == 1 || num_channels == 2 || num_channels == 4 || num_channels == 8) &&
- (bit_depth == 16 || bit_depth == 32) &&
- num_buffers > 0 &&
- buffer_size >= bytes_per_sample)
- {
- // buffer lengths must be 16 byte aligned for VCHI
- int size = (buffer_size + 15) & ~15;
- AUDIOPLAY_STATE_T *st;
- // buffer offsets must also be 16 byte aligned for VCHI
- st = calloc(1, sizeof(AUDIOPLAY_STATE_T));
- if(st)
- {
- OMX_ERRORTYPE error;
- OMX_PARAM_PORTDEFINITIONTYPE param;
- OMX_AUDIO_PARAM_PCMMODETYPE pcm;
- int32_t s;
- ret = 0;
- *handle = st;
- // create and start up everything
- s = sem_init(&st->sema, 0, 1);
- assert(s == 0);
- st->bytes_per_sample = bytes_per_sample;
- st->num_buffers = num_buffers;
- st->client = ilclient_init();
- assert(st->client != NULL);
- ilclient_set_empty_buffer_done_callback(st->client, input_buffer_callback, st);
- error = OMX_Init();
- assert(error == OMX_ErrorNone);
- ilclient_create_component(st->client, &st->audio_render, "audio_render", ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_DISABLE_ALL_PORTS);
- assert(st->audio_render != NULL);
- st->list[0] = st->audio_render;
- // set up the number/size of buffers
- memset(¶m, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
- param.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
- param.nVersion.nVersion = OMX_VERSION;
- param.nPortIndex = 100;
- error = OMX_GetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m);
- assert(error == OMX_ErrorNone);
- param.nBufferSize = size;
- param.nBufferCountActual = num_buffers;
- error = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m);
- assert(error == OMX_ErrorNone);
- // set the pcm parameters
- memset(&pcm, 0, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE));
- pcm.nSize = sizeof(OMX_AUDIO_PARAM_PCMMODETYPE);
- pcm.nVersion.nVersion = OMX_VERSION;
- pcm.nPortIndex = 100;
- pcm.nChannels = num_channels;
- pcm.eNumData = OMX_NumericalDataSigned;
- pcm.eEndian = OMX_EndianLittle;
- pcm.nSamplingRate = sample_rate;
- pcm.bInterleaved = OMX_TRUE;
- pcm.nBitPerSample = bit_depth;
- pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;
- switch(num_channels) {
- case 1:
- pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
- break;
- case 8:
- pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
- pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
- pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
- pcm.eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
- pcm.eChannelMapping[4] = OMX_AUDIO_ChannelLR;
- pcm.eChannelMapping[5] = OMX_AUDIO_ChannelRR;
- pcm.eChannelMapping[6] = OMX_AUDIO_ChannelLS;
- pcm.eChannelMapping[7] = OMX_AUDIO_ChannelRS;
- break;
- case 4:
- pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
- pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
- pcm.eChannelMapping[2] = OMX_AUDIO_ChannelLR;
- pcm.eChannelMapping[3] = OMX_AUDIO_ChannelRR;
- break;
- case 2:
- pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
- pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
- break;
- }
- error = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamAudioPcm, &pcm);
- assert(error == OMX_ErrorNone);
- ilclient_change_component_state(st->audio_render, OMX_StateIdle);
- if(ilclient_enable_port_buffers(st->audio_render, 100, NULL, NULL, NULL) < 0)
- {
- // error
- ilclient_change_component_state(st->audio_render, OMX_StateLoaded);
- ilclient_cleanup_components(st->list);
- error = OMX_Deinit();
- assert(error == OMX_ErrorNone);
- ilclient_destroy(st->client);
- sem_destroy(&st->sema);
- free(st);
- *handle = NULL;
- return -1;
- }
- ilclient_change_component_state(st->audio_render, OMX_StateExecuting);
- }
- }
- return ret;
- }
- int32_t audioplay_delete(AUDIOPLAY_STATE_T *st)
- {
- OMX_ERRORTYPE error;
- ilclient_change_component_state(st->audio_render, OMX_StateIdle);
- error = OMX_SendCommand(ILC_GET_HANDLE(st->audio_render), OMX_CommandStateSet, OMX_StateLoaded, NULL);
- assert(error == OMX_ErrorNone);
- ilclient_disable_port_buffers(st->audio_render, 100, st->user_buffer_list, NULL, NULL);
- ilclient_change_component_state(st->audio_render, OMX_StateLoaded);
- ilclient_cleanup_components(st->list);
- error = OMX_Deinit();
- assert(error == OMX_ErrorNone);
- ilclient_destroy(st->client);
- sem_destroy(&st->sema);
- free(st);
- return 0;
- }
- uint8_t *audioplay_get_buffer(AUDIOPLAY_STATE_T *st)
- {
- OMX_BUFFERHEADERTYPE *hdr = NULL;
- hdr = ilclient_get_input_buffer(st->audio_render, 100, 0);
- if(hdr)
- {
- // put on the user list
- sem_wait(&st->sema);
- hdr->pAppPrivate = st->user_buffer_list;
- st->user_buffer_list = hdr;
- sem_post(&st->sema);
- }
- return hdr ? hdr->pBuffer : NULL;
- }
- int32_t audioplay_play_buffer(AUDIOPLAY_STATE_T *st,
- uint8_t *buffer,
- uint32_t length)
- {
- OMX_BUFFERHEADERTYPE *hdr = NULL, *prev = NULL;
- int32_t ret = -1;
- if(length % st->bytes_per_sample)
- return ret;
- sem_wait(&st->sema);
- // search through user list for the right buffer header
- hdr = st->user_buffer_list;
- while(hdr != NULL && hdr->pBuffer != buffer && hdr->nAllocLen < length)
- {
- prev = hdr;
- hdr = hdr->pAppPrivate;
- }
- if(hdr) // we found it, remove from list
- {
- ret = 0;
- if(prev)
- prev->pAppPrivate = hdr->pAppPrivate;
- else
- st->user_buffer_list = hdr->pAppPrivate;
- }
- sem_post(&st->sema);
- if(hdr)
- {
- OMX_ERRORTYPE error;
- hdr->pAppPrivate = NULL;
- hdr->nOffset = 0;
- hdr->nFilledLen = length;
- error = OMX_EmptyThisBuffer(ILC_GET_HANDLE(st->audio_render), hdr);
- assert(error == OMX_ErrorNone);
- }
- return ret;
- }
- int32_t audioplay_set_dest(AUDIOPLAY_STATE_T *st, const char *name)
- {
- int32_t success = -1;
- OMX_CONFIG_BRCMAUDIODESTINATIONTYPE ar_dest;
- if (name && strlen(name) < sizeof(ar_dest.sName))
- {
- OMX_ERRORTYPE error;
- memset(&ar_dest, 0, sizeof(ar_dest));
- ar_dest.nSize = sizeof(OMX_CONFIG_BRCMAUDIODESTINATIONTYPE);
- ar_dest.nVersion.nVersion = OMX_VERSION;
- strcpy((char *)ar_dest.sName, name);
- error = OMX_SetConfig(ILC_GET_HANDLE(st->audio_render), OMX_IndexConfigBrcmAudioDestination, &ar_dest);
- assert(error == OMX_ErrorNone);
- success = 0;
- }
- return success;
- }
- uint32_t audioplay_get_latency(AUDIOPLAY_STATE_T *st)
- {
- OMX_PARAM_U32TYPE param;
- OMX_ERRORTYPE error;
- memset(¶m, 0, sizeof(OMX_PARAM_U32TYPE));
- param.nSize = sizeof(OMX_PARAM_U32TYPE);
- param.nVersion.nVersion = OMX_VERSION;
- param.nPortIndex = 100;
- error = OMX_GetConfig(ILC_GET_HANDLE(st->audio_render), OMX_IndexConfigAudioRenderingLatency, ¶m);
- assert(error == OMX_ErrorNone);
- return param.nU32;
- }
- #define CTTW_SLEEP_TIME 10
- #define MIN_LATENCY_TIME 20
- const int SAMPLERATE[] = {8000, 11025, 44100, 96000};
- const int BITDEPTH[] = {16, 32};
- const int CHANNELS[] = {1, 2, 4, 8};
- static const char *audio_dest[] = {"local", "hdmi"};
- void play_api_test(int samplerate, int bitdepth, int nchannels, int dest)
- {
- AUDIOPLAY_STATE_T *st;
- int32_t ret;
- unsigned int i, j, n;
- int phase = 0;
- int inc = 256<<16;
- int dinc = 0;
- int buffer_size = (BUFFER_SIZE_SAMPLES * bitdepth * nchannels)>>3;
- assert(dest == 0 || dest == 1);
- ret = audioplay_create(&st, samplerate, nchannels, bitdepth, 10, buffer_size);
- assert(ret == 0);
- ret = audioplay_set_dest(st, audio_dest[dest]);
- assert(ret == 0);
- ModPlug_Settings settings;
- //memset(&settings, 0, sizeof(settings));
- ModPlug_GetSettings(&settings);
- settings.mFlags = 0;
- settings.mChannels = nchannels;
- settings.mBits = bitdepth;
- settings.mFrequency = samplerate;
- settings.mResamplingMode = MODPLUG_RESAMPLE_NEAREST;
- settings.mLoopCount = -1;
- settings.mMaxMixChannels = 32;
- ModPlug_SetSettings(&settings);
- ModPlugFile* _module = ModPlug_Load((const void*) rawData, sizeof(rawData));
- // iterate for 5 seconds worth of packets
- int res = 0;
- //for (n=0; n<((samplerate * 5)/ BUFFER_SIZE_SAMPLES); n++)
- do
- {
- uint8_t *buf;
- int16_t *p;
- uint32_t latency;
- //printf("buffer.."); fflush(stdout);
- // ez hulyeseg
- //while((buf = audioplay_get_buffer(st)) == NULL) usleep(10);
- buf = audioplay_get_buffer(st);
- p = (int16_t *) buf;
- printf("render.."); fflush(stdout);
- res = ModPlug_Read(_module, (void*) p, nchannels*BUFFER_SIZE_SAMPLES*sizeof(*p));
- printf("latecy, "); fflush(stdout);
- // todo: threadbe vagni mindezt, es elfelejteni, hogy van.
- // threadet minden render utan felfuggeszteni, es visszaterni akkor amikor lejar a buffer
- // ez mi a fene
- // de ha kiszedem, akkor nem megy
- while((latency = audioplay_get_latency(st)) > (samplerate * (MIN_LATENCY_TIME + CTTW_SLEEP_TIME) / 1000)) usleep(CTTW_SLEEP_TIME*100);
- printf("kesz, "); fflush(stdout);
- ret = audioplay_play_buffer(st, buf, buffer_size);
- printf("play\n"); fflush(stdout);
- //assert(ret == 0);
- } while (res);
- ModPlug_Unload(_module);
- audioplay_delete(st);
- }
- int main (int argc, char **argv)
- {
- // 0=headphones, 1=hdmi
- int audio_dest = 0;
- // audio sample rate in Hz
- int samplerate = 96000;
- // numnber of audio channels
- int channels = 2;
- // number of bits per sample
- int bitdepth = 16;
- bcm_host_init();
- if (argc > 1)
- audio_dest = atoi(argv[1]);
- printf("Outputting audio to %s\n", audio_dest==0 ? "analogue":"hdmi");
- play_api_test(samplerate, bitdepth, channels, audio_dest);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement