/**************************************************************************** DESCRIPTION handles the internal cvc messages / messages from the dsp */ void CsrA2dpDecoderPluginInternalMessage( A2dpPluginTaskdata *task ,uint16 id , Message message ) { switch(id) { case MESSAGE_FROM_KALIMBA: { const DSP_REGISTER_T *m = (const DSP_REGISTER_T *) message; PRINT(("DECODER: msg id[%x] a[%x] b[%x] c[%x] d[%x]\n", m->id, m->a, m->b, m->c, m->d)); switch ( m->id ) { case MUSIC_READY_MSG: { if (DECODER) { KalimbaSendMessage(MUSIC_LOADPARAMS_MSG, MUSIC_PS_BASE, 0, 0, 0); /*A2dp is now loaded, signal that tones etc can be scheduled*/ AUDIO_BUSY = NULL ; PRINT(("DECODER: DECODER_READY \n")); CsrA2dpDecoderPluginSetMode(DECODER->mode, task, 0); MusicConnectAudio (task, DECODER->stereo); } } break; case MUSIC_CODEC_MSG: { uint16 lOutput_gain_l = m->a; uint16 lOutput_gain_r = m->b; if (DECODER) { CodecSetOutputGainNow(DECODER->codec_task, lOutput_gain_l, left_ch); CodecSetOutputGainNow(DECODER->codec_task, lOutput_gain_r, right_ch); } } break; case KALIMBA_MSG_SOURCE_CLOCK_MISMATCH_RATE: { MAKE_AUDIO_MESSAGE(AUDIO_PLUGIN_DSP_MSG); message->id = KALIMBA_MSG_SOURCE_CLOCK_MISMATCH_RATE; message->value = m->a; MessageSend(DECODER->app_task, AUDIO_PLUGIN_DSP_MSG, message); break; } } } break; default: break ; } }
void CsrSubwooferPluginConnect(Sink audio_sink, Task codec_task, Task app_task, subwooferPluginConnectParams * params) { FILE_INDEX index; /* Update the current DSP status */ SetCurrentDspStatus(DSP_LOADING); /* Give Kalimba the plugin task so it knows where to send messages */ (void) MessageCancelAll( (TaskData*)&csr_subwoofer_plugin, MESSAGE_FROM_KALIMBA); MessageKalimbaTask( (TaskData*)&csr_subwoofer_plugin ); /* Load the Subwofoer DSP application - Panic if it could not be loaded */ index = PanicFalse( FileFind(FILE_ROOT, kal, sizeof(kal) - 1) ); PanicFalse( KalimbaLoad(index) ); /* update current DSP status */ SetCurrentDspStatus(DSP_LOADED_IDLE); /* Allocate memory to store the plugin data */ plugin_data = (subwooferPluginData*)PanicUnlessMalloc(sizeof(subwooferPluginData)); /* Initialise the plugin data based on parameters supplied by the application */ plugin_data->audio_source = StreamSourceFromSink(audio_sink); plugin_data->swat_system_volume_db = params->swat_system_volume_db; plugin_data->swat_trim_gain_db = params->swat_trim_gain_db; plugin_data->adc_volume_index = params->adc_volume; plugin_data->input = params->input; plugin_data->output = params->output; plugin_data->sample_rate = params->sample_rate; plugin_data->adc_sample_rate = params->adc_sample_rate; plugin_data->codec_task = codec_task; plugin_data->app_task = app_task; plugin_data->dsp_set_sample_rate = 0; /* set later in response to AUDIO_PLUGIN_SET_MODE_MSG */ /* Zero the codecs output gain */ CodecSetOutputGainNow(plugin_data->codec_task, 0, left_and_right_ch); CodecSetInputGainNow(plugin_data->codec_task, 0, left_and_right_ch); /* If using the ADC, set the ADC source */ if (plugin_data->input == SUBWOOFER_INPUT_ADC) { /* Get the ADC source */ plugin_data->audio_source = StreamAudioSource(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A); } /* Disconnect the source in case it's currently being disposed */ StreamDisconnect(StreamSourceFromSink(audio_sink), 0); PRINT(("[SW_PLUGIN] : CsrSubwooferPluginConnect - complete\n")); }
void handleInternalPluginMessage(Task task, MessageId id, Message message) { switch(id) { case MESSAGE_FROM_KALIMBA: { const DSP_REGISTER_T *msg = (const DSP_REGISTER_T *)message; /* Handle the message sent from Kalimba */ switch(msg->id) { case MUSIC_READY_MSG: { PRINT(("[SW_PLUGIN] : MUSIC_READY_MSG a[%x] b[%x] c[%x] d[%x]\n", msg->a, msg->b, msg->c, msg->d)); if (plugin_data) { /* Send parameters PSKEY to DSP */ KalimbaSendMessage(MUSIC_LOADPARAMS_MSG, MUSIC_PS_BASE, 0, 0, 0); } else { SetCurrentDspStatus(DSP_ERROR); } } break; case MUSIC_PARAMS_LOADED_MSG: { /* Send a message to the app to inform the number of subwoofer volume gains (for ADC mode) */ AUDIO_PLUGIN_DSP_IND_T * message = PanicUnlessNew(AUDIO_PLUGIN_DSP_IND_T); message->id = SUB_PLUGIN_NUM_VOL_GAINS; message->size_value = 1; message->value[0] = msg->a; MessageSend(plugin_data->app_task, AUDIO_PLUGIN_DSP_IND, message); PRINT(("[SW_PLUGIN] : MUSIC_PARAMS_LOADED_MSG a[%x] b[%x] c[%x] d[%x]\n", msg->a, msg->b, msg->c, msg->d)); /* Connect input and output streams */ connectAudioStreams(); /* Send Volume to DSP */ KalimbaSendMessage(MUSIC_VOLUME_MSG, plugin_data->swat_system_volume_db, plugin_data->swat_trim_gain_db, 0, plugin_data->adc_volume_index); /* Set the DSP status */ SetCurrentDspStatus(DSP_RUNNING); /* Send GO to DSP */ PanicFalse(KalimbaSendMessage(KALIMBA_MSG_GO, 0, 0, 0, 0)); /* Send a message to the app to inform that the plugin is ready to recieve audio data */ MessageSend(plugin_data->app_task, AUDIO_PLUGIN_DSP_READY_FOR_DATA, 0); } break; case MUSIC_CODEC_MSG: { PRINT(("[SW_PLUGIN] : MUSIC_CODEC_MSG a[%x] b[%x] c[%x] d[%x]\n", msg->a, msg->b, msg->c, msg->d)); /* Parameters for this message : */ /* msg->a BITS[0-3] = input gain */ /* msg->a BIT[15] = enable/disable mic preamp */ /* msg->b = output gain */ /* Only set the input gain if using the ADC input (ESCO/L2CAP inputs don't use the ADC) */ if (plugin_data->input == SUBWOOFER_INPUT_ADC) { PRINT(("[SW PLUGIN] : Set ADC input GAIN[%x] Pre-amp enable[%x]\n", (msg->a & 0x1F), (msg->a>>15) & 0x1)); AudioPluginSetMicGain(plugin_data->audio_source, FALSE, (msg->a & 0x1F), (msg->a>>15) & 0x1); } PRINT(("[SW PLUGIN] : Set DAC GAIN[%x]\n", msg->b)); /* Set the codec output gain according to what the DSP sent */ if (plugin_data->output == SUBWOOFER_OUTPUT_I2S) { CsrI2SAudioOutputSetVolume(FALSE, msg->b, msg->b, FALSE); } else { CodecSetOutputGainNow(plugin_data->codec_task, msg->b, left_and_right_ch); } } break; case MUSIC_CUR_EQ_BANK: { PRINT(("[SW_PLUGIN] : MUSIC_CUR_EQ_BANK a[%x] b[%x] c[%x] d[%x]\n", msg->a, msg->b, msg->c, msg->d)); /* TODO */ } break; case MUSIC_SIGNAL_DETECT_STATUS: { /* msg->a = 1 if playing audio, 0 if audio is silent */ PRINT(("[SW_PLUGIN] : MUSIC_SIGNAL_DETECT_STATUS a[%x]\n", msg->a)); if (msg->a) { /* Audio on wired input has been detected - Inform client task */ AUDIO_PLUGIN_DSP_IND_T * message = PanicUnlessNew(AUDIO_PLUGIN_DSP_IND_T); message->id = SUB_PLUGIN_ADC_SIGNAL_ACTIVE; message->size_value = 1; message->value[0] = 0; MessageSend(plugin_data->app_task, AUDIO_PLUGIN_DSP_IND, message); } else { /* Audio on wired input is now silent - Inform client task */ AUDIO_PLUGIN_DSP_IND_T * message = PanicUnlessNew(AUDIO_PLUGIN_DSP_IND_T); message->id = SUB_PLUGIN_ADC_SIGNAL_IDLE; message->size_value = 1; message->value[0] = 0; MessageSend(plugin_data->app_task, AUDIO_PLUGIN_DSP_IND, message); } } break; default: { PRINT(("[SW_PLUGIN] : Unhandled message from Kalimba ID[%x]\n", msg->id)); } break; } } break; default: { PRINT(("[SW_PLUGIN] : Unhandled internal message ID[%x]\n", id)); } break; }
/**************************************************************************** DESCRIPTION This function connects a synchronous audio stream to the pcm subsystem */ void CsrA2dpDecoderPluginConnect( A2dpPluginTaskdata *task, Sink audio_sink , Task codec_task , uint16 volume , uint32 rate , bool stereo , AUDIO_MODE_T mode , const void * params , Task app_task ) { FILE_INDEX index = FILE_NONE; char* kap_file = NULL ; /* Only need to read the PS Key value once */ if (!pskey_read) { if (PsFullRetrieve(PSKEY_MAX_CLOCK_MISMATCH, &val_pskey_max_mismatch, sizeof(uint16)) == 0) val_pskey_max_mismatch = 0; pskey_read = TRUE; } switch ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant) { case SBC_DECODER: kap_file = "sbc_decoder/sbc_decoder.kap"; break; case MP3_DECODER: kap_file = "mp3_decoder/mp3_decoder.kap"; break; case AAC_DECODER: kap_file = "aac_decoder/aac_decoder.kap"; break; case FASTSTREAM_SINK: kap_file = "faststream_sink/faststream_sink.kap"; break; default: Panic(); break; } /*ensure that the messages received are from the correct kap file*/ (void) MessageCancelAll( (TaskData*) task, MESSAGE_FROM_KALIMBA); MessageKalimbaTask( (TaskData*) task ); index = FileFind(FILE_ROOT,(const char *) kap_file ,strlen(kap_file)); if (index == FILE_NONE) Panic(); if (!KalimbaLoad(index)) Panic(); DECODER = (DECODER_t*)PanicUnlessMalloc (sizeof (DECODER_t) ) ; DECODER->media_sink = audio_sink ; DECODER->codec_task = codec_task ; DECODER->volume = volume; DECODER->mode = mode; DECODER->stereo = stereo; DECODER->params = (uint16) params; DECODER->rate = rate; DECODER->app_task = app_task; if ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant == AAC_DECODER) { /* Workaround for AAC+ sources that negotiate sampling frequency at half the actual value */ if (rate < 32000) DECODER->rate = rate * 2; } CodecSetOutputGainNow(DECODER->codec_task, 0, left_and_right_ch); StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0)); StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1)); PanicFalse(PcmClearRouting(0)); PanicFalse(PcmClearRouting(1)); /* For sinks disconnect the source in case its currently being disposed. */ StreamDisconnect(StreamSourceFromSink(audio_sink), 0); PRINT(("DECODER: CsrA2dpDecoderPluginConnect completed\n")); }