void PlayBuffer(short *PCMData, int size) { AUDIOPLAY_STATE_T *st; int32_t ret; int phase = 0; int inc = 256<<16; int dinc = 0; int buffer_bytes = (BUFFER_SIZE_SAMPLES * bitdepth * OUT_CHANNELS(nchannels))>>3; ret = audioplay_create(&st, samplerate, nchannels, bitdepth, bufferCount, buffer_bytes); ret = audioplay_set_dest(st, audio_dest[dest]); int sectorNumber= (size-1)/BUFFER_SIZE_SAMPLES+1; int i; for (i=0;i<sectorNumber;i++) { uint8_t *buf; int16_t *p; uint32_t latency; while((buf = audioplay_get_buffer(st)) == NULL) usleep(CTTW_SLEEP_TIME*1000); p = (int16_t *) buf; if ((i+1)*BUFFER_SIZE_SAMPLES<=size) { memcpy(p,PCMData+i*BUFFER_SIZE_SAMPLES,sizeof(short)*BUFFER_SIZE_SAMPLES); } else { memcpy(p,PCMData+i*BUFFER_SIZE_SAMPLES,sizeof(short)*(size-i*BUFFER_SIZE_SAMPLES)); memset(p+size-i*BUFFER_SIZE_SAMPLES,0,sizeof(short)*((i+1)*BUFFER_SIZE_SAMPLES-size)); } // try and wait for a minimum latency time (in ms) before // sending the next packet while((latency = audioplay_get_latency(st)) > (samplerate * (MIN_LATENCY_TIME + CTTW_SLEEP_TIME) / 1000)) usleep(CTTW_SLEEP_TIME*1000); //if (i==m_CurPlayStartSector) usleep(CTTW_SLEEP_TIME*1000); ret = audioplay_play_buffer(st, buf, buffer_bytes); } audioplay_delete(st); }
} 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 * OUT_CHANNELS(num_channels)) >> 3; int32_t ret = -1; *handle = NULL; // basic sanity check on arguments if(sample_rate >= 8000 && sample_rate <= 192000 && (num_channels >= 1 && 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;
int32_t ilctts_create( TTSRENDER_STATE_T **component, uint32_t sample_rate, uint32_t num_channels, uint32_t bit_depth, uint32_t num_buffers, uint32_t buffer_size_ms, BUFFER_SIZE_TYPE_T buffer_size_type, uint32_t ringbuffer_length ) { ENTER(LOGLEVEL_1, "ilctts_create"); SHOW(LOGLEVEL_5, "Sample rate: %d", sample_rate); SHOW(LOGLEVEL_5, "Number of channels: %d", num_channels); SHOW(LOGLEVEL_5, "Bit depth: %d", bit_depth); SHOW(LOGLEVEL_5, "Number of buffers: %d", num_buffers); SHOW(LOGLEVEL_5, "Buffer size: %d", buffer_size_ms); SHOW(LOGLEVEL_5, "Ring buffer length: %d", ringbuffer_length); int32_t ret; uint32_t buffer_size; OMX_ERRORTYPE omx_err; TTSRENDER_STATE_T *st; *component = NULL; st = calloc(1, sizeof(TTSRENDER_STATE_T)); OMX_PARAM_PORTDEFINITIONTYPE param; OMX_AUDIO_PARAM_PCMMODETYPE pcm; int32_t s; *component = st; // create and start up everything // initialise buffer list semaphore s = sem_init(&st->buffer_list_sema, 0, 1); if (s < 0) { ERROR("sem_init returned error initializing buffer list semaphore in ilctts_create: %d", s); return -1; } // initial value of ringbuffer_empty_sema is 1 because at startup there is space s = sem_init(&st->ringbuffer_empty_sema, 0, 1); if (s < 0) { ERROR("sem_init returned error initializing ringbuffer_empty_sema in ilctts_create: %d", s); return -1; } // initial value of ringbuffer_data_sema is 0 because at startup there is no data s = sem_init(&st->ringbuffer_data_sema, 0, 0); if (s < 0) { ERROR("sem_init returned error initializing ringbuffer_data_sema in ilctts_create: %d", s); return -1; } // free_buffer mutex and cv pthread_mutex_init(&st->free_buffer_mutex, NULL); pthread_cond_init(&st->free_buffer_cv, NULL); // ringbuffer mutex pthread_mutex_init(&st->ringbuffer_mutex, NULL); //pthread_cond_init(&st->ringbuffer_cv, NULL); st->sample_rate = sample_rate; st->num_channels = num_channels; st->bit_depth = bit_depth; st->bytes_per_sample = (bit_depth * OUT_CHANNELS(num_channels)) >> 3; if (buffer_size_type == BS_MILLISECONDS) { // supplied buffer size was in milliseconds, calculate the byte size // note: calc_buffer_size_from_ms returns buffer size aligned for VCHI buffer_size = calc_buffer_size_from_ms(sample_rate, bit_depth, num_channels, buffer_size_ms, 1); } else { // supplied buffer size was in bytes // buffer size must be 16 byte aligned for VCHI buffer_size = (buffer_size_ms + 15) & ~15; } SHOW(LOGLEVEL_5, "Bytes per sample: %d", st->bytes_per_sample); SHOW(LOGLEVEL_5, "Calculated buffer size: %d", buffer_size); st->num_buffers = num_buffers; st->client = ilclient_init(); st->tts_stop = 0; st->tts_pause_state = TTS_PAUSE_OFF; st->ringbuffer = ringbuffer_init(ringbuffer_length); if (st->ringbuffer == NULL) { ERROR("ringbuffer_init failed in ilctts_create", ""); return -1; } // set up callbacks ilclient_set_empty_buffer_done_callback(st->client, input_buffer_callback, st); //ilclient_set_configchanged_callback(st->client, config_changed_callback, st); //ilclient_set_port_settings_callback(st->client, port_settings_changed_callback, st); ret = ilclient_create_component(st->client, &st->audio_render, "audio_render", ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_DISABLE_ALL_PORTS); if (ret == -1) { ERROR("ilclcient_create_component returned error in ilctts_create: %d", ret); return ret; } st->list[0] = st->audio_render; // set up the number/size of buffers OMX_INIT_STRUCTURE(param); param.nPortIndex = 100; omx_err = OMX_GetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m); if (omx_err != OMX_ErrorNone) { ERROR("OMX_GetParameter returned error in ilctts_create: %d", omx_err); return -1; } // set the buffer size to the requested size, or the minimum size returned, whichever is greater st->buffer_size = max(buffer_size, param.nBufferSize); SHOW(LOGLEVEL_3, "Buffer size set to: %d", st->buffer_size); param.nBufferSize = st->buffer_size; param.nBufferCountActual = max(st->buffer_count, param.nBufferCountMin); omx_err = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, ¶m); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SetParameter returned error in ilctts_create: %d", omx_err); return -1; } // set the pcm parameters OMX_INIT_STRUCTURE(pcm); pcm.nPortIndex = 100; pcm.nChannels = OUT_CHANNELS(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(st->num_channels) { case 1: pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF; break; case 3: pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF; pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; break; case 8: pcm.eChannelMapping[7] = OMX_AUDIO_ChannelRS; case 7: pcm.eChannelMapping[6] = OMX_AUDIO_ChannelLS; case 6: pcm.eChannelMapping[5] = OMX_AUDIO_ChannelRR; case 5: pcm.eChannelMapping[4] = OMX_AUDIO_ChannelLR; case 4: pcm.eChannelMapping[3] = OMX_AUDIO_ChannelLFE; pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF; case 2: pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF; pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF; break; } omx_err = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamAudioPcm, &pcm); if (omx_err != OMX_ErrorNone) { ERROR("OMX_SetParameter returned error in ilctts_create: %d", omx_err); return -1; } // this function waits for the command to complete ret = ilclient_change_component_state(st->audio_render, OMX_StateIdle); if (ret < 0) { ERROR("ilctts_change_component_state returned error in ilctts_create: %d", ret); return -1; } ret = ilclient_enable_port_buffers(st->audio_render, 100, NULL, NULL, NULL); if (ret < 0) { ERROR("ilclient_enable_port_buffers returned error in ilctts_create: %d", ret); ilclient_change_component_state(st->audio_render, OMX_StateLoaded); ilclient_cleanup_components(st->list); omx_err = OMX_Deinit(); ilclient_destroy(st->client); destroy_semaphores(st); destroy_mutexes(st); ringbuffer_destroy(st->ringbuffer); // need to destroy and free other stuff here? free(st); *component = NULL; return -1; } INFO(LOGLEVEL_1, "Setting state to executing in ilctts_create"); return ilclient_change_component_state(st->audio_render, OMX_StateExecuting); } // end ilctts_create