📄 audio.c
字号:
RMAudioEnginePropertyID_SampleFrequencyFromSource, &sf, sizeof(sf), 0);}/* Stops capture, and playback of captured audio */RMstatus cap_audio_stop_passthrough( struct cap_audio_instance *pAudio){ RMstatus err; RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->pAudioSource == NULL) { return RM_OK; } // Restore internal audio engine clock if (pAudio->Setup.ExternalClk) { if (! pAudio->Setup.SampleRate) { pAudio->Setup.SampleRate = pAudio->cap_opt->SampleRate; } pAudio->Setup.ExternalClk = FALSE; err = cap_audio_set_sample_clock(pAudio); pAudio->Setup.ExternalClk = TRUE; } // stop capture err = cap_audio_stop_capture(pAudio); // stop playback err = DCCStopAudioSource(pAudio->pAudioSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot stop audio decoder! %s\n", RMstatusToString(err))); } // close playback err = DCCCloseAudioSource(pAudio->pAudioSource); pAudio->pAudioSource = NULL; if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error, cannot close audio decoder! %s\n", RMstatusToString(err))); } return err;}/* Initializes and starts capture, and playback of captured audio *//* This function needs audio_opt for the audio playback *//* If your application is using a different method to set up the audio decoder, follow this example for the passthrough */RMstatus cap_audio_start_passthrough( struct cap_audio_instance *pAudio){ RMstatus err; struct DCCAudioProfile audio_profile; RMuint32 audio_decoder, audio_engine, audio_timer; RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER;// if (pAudio->audio_opt == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->pAudioSource) { cap_audio_stop_passthrough(pAudio); } // Open AudioDecoder audio_profile.BitstreamFIFOSize = AUDIO_FIFO_SIZE; audio_profile.XferFIFOCount = XFER_FIFO_COUNT; audio_profile.DemuxProgramID = pAudio->Setup.AudioEngineID * 2; audio_profile.AudioEngineID = pAudio->Setup.AudioEngineID; audio_profile.AudioDecoderID = pAudio->Setup.AudioDecoderID; audio_profile.STCID = pAudio->Setup.STCTimerNumber; err = DCCOpenAudioDecoderSource(pAudio->pDCC, &audio_profile, &(pAudio->pAudioSource)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot open audio decoder! %s\n", RMstatusToString(err))); return err; } err = DCCGetAudioDecoderSourceInfo(pAudio->pAudioSource, &audio_decoder, &audio_engine, &audio_timer); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error getting audio decoder source information! %s\n", RMstatusToString(err))); return err; } // apply the sample rate, rest of output setup needs to be already done by application err = cap_audio_set_sample_clock(pAudio); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error applying audio engine sample rate! %s\n", RMstatusToString(err))); return err; } //TODO needs to be done by main application // apply the audio format - uninit, set codec, set specific parameters, init// err = apply_audio_decoder_options(pAudio->dcc_info, pAudio->audio_opt);// if (RMFAILED(err)) {// RMDBGLOG((ENABLE, "Error applying audio_decoder_options! %s\n", RMstatusToString(err)));// return err;// } // Send Play command to audio playback err = DCCPlayAudioSource(pAudio->pAudioSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot play audio decoder! %s\n", RMstatusToString(err))); return err; } // Start audio capture err = cap_audio_start_capture(pAudio); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error starting audio capture! %s\n", RMstatusToString(err))); return err; } return err;}/** Detetct audio codec from 86xx SI channel status and from Pc/Pe values parsed by audio uCode Input: stat->ChannelStatus stat->Pc stat->Pe pAudio->Setup.BitsPerSample (capture 16 or 24 bit from I2S) Fills in: pAudio->auto_detect_codec (TRUE: codec could not be determined) pAudio->audio_opt->Codec pAudio->audio_opt optional values for that codec pAudio->audio_opt->OutputChannels (PCM only)*//* This function needs audio_opt for the audio playback */RMstatus cap_audio_get_codec_from_spdif_info( struct cap_audio_instance *pAudio, struct AudioEngine_InputSPDIFStatus_type *stat){ RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->cap_opt == NULL) return RM_FATALINVALIDPOINTER; //RMDBGLOG((ENABLE, "get_spdif_codec(ChStat:0x%08lX, Pc:0x%02X, Pe:0x%02X)\n", stat->ChannelStatus, stat->Pc, stat->Pe)); if (stat->ChannelStatus & 0x0002) { if ((stat->Pc & 0x1F) == 0) return RM_OK; // Null data, no change if ((stat->Pc & 0x1F) == 3) return RM_OK; // Pause data, no change if (RMunshiftBits(stat->Pc, 3, 13) != pAudio->Setup.CaptureBitstream) return RM_OK; // Not our stream } pAudio->auto_detect_codec = FALSE; if (stat->ChannelStatus & 0x0002) { RMDBGLOG((ENABLE, "Detected Codec: ")); switch (stat->Pc & 0x1F) { default: RMDBGPRINT((ENABLE, "Unknown or reserved codec type: %u\n", stat->Pc & 0x1F)); if (0) case 0: RMDBGPRINT((ENABLE, "Null Data\n")); if (0) case 3: RMDBGPRINT((ENABLE, "Pause\n")); if (0) case 2: RMDBGPRINT((ENABLE, "SMPTE 338M Time Stamp Data\n")); if (0) case 27: RMDBGPRINT((ENABLE, "SMPTE 338M KLV Data\n")); if (0) case 28: RMDBGPRINT((ENABLE, "SMPTE 338M Dolby E Data\n")); if (0) case 29: RMDBGPRINT((ENABLE, "SMPTE 338M Captioning Data\n")); if (0) case 30: RMDBGPRINT((ENABLE, "SMPTE 338M User Data\n")); pAudio->cap_opt->auto_detect_codec = TRUE; break; case 1: RMDBGPRINT((ENABLE, "AC3\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_AC3; pAudio->cap_opt->Ac3Params.OutputChannels = Ac3_LR; break; case 4: RMDBGPRINT((ENABLE, "MPEG 1 Layer 1\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 5: RMDBGPRINT((ENABLE, "MPEG 1 Layer 2 or 3, MPEG 2 w/o extension\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 6: RMDBGPRINT((ENABLE, "MPEG 2 w/ extension\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 7: RMDBGPRINT((ENABLE, "MPEG 2 AAC\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_AAC; // TODO 0, 1, 2 or 3? pAudio->cap_opt->AACParams.InputFormat = 0; pAudio->cap_opt->AACParams.OutputChannels = Aac_LR; break; case 8: RMDBGPRINT((ENABLE, "MPEG 2 Layer 1\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 9: RMDBGPRINT((ENABLE, "MPEG 2 Layer 2\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 10: RMDBGPRINT((ENABLE, "MPEG 2 Layer 3\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 11: RMDBGPRINT((ENABLE, "DTS Type I\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_DTS; pAudio->cap_opt->DtsParams.OutputChannels = Dts_LR; break; case 12: RMDBGPRINT((ENABLE, "DTS Type II\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_DTS; pAudio->cap_opt->DtsParams.OutputChannels = Dts_LR; break; case 13: RMDBGPRINT((ENABLE, "DTS Type III\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_DTS; pAudio->cap_opt->DtsParams.OutputChannels = Dts_LR; break; case 14: RMDBGPRINT((ENABLE, "ATRAC (unsupported)\n")); pAudio->auto_detect_codec = TRUE; //pAudio->cap_opt->Codec = ; break; case 15: RMDBGPRINT((ENABLE, "ATRAC 2/3 (unsupported)\n")); pAudio->auto_detect_codec = TRUE; //pAudio->cap_opt->Codec = ; break; case 18: RMDBGPRINT((ENABLE, "WMA Pro\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_WMAPRO; break; case 31: switch (stat->Pe) { default: RMDBGPRINT((ENABLE, "Unknown extended data-type: %u\n", stat->Pe)); pAudio->auto_detect_codec = TRUE; break; } break; } } else { RMDBGLOG((ENABLE, "Detected Codec: PCM\n")); pAudio->auto_detect_codec = FALSE; pAudio->cap_opt->Codec = AudioDecoder_Codec_PCM; if ((pAudio->Setup.CaptureSource == 0) && (pAudio->Setup.BitsPerSample >= 24)) { // 24 bit on I2S only pAudio->cap_opt->SubCodec = 0; pAudio->cap_opt->PcmCdaParams.BitsPerSample = 24; pAudio->cap_opt->PcmCdaParams.MsbFirst = ! pAudio->Setup.AudioInLSBfirst; } else { pAudio->cap_opt->SubCodec = 1; pAudio->cap_opt->LpcmVobParams.BitsPerSample = 16; } pAudio->cap_opt->OutputChannels = Audio_Out_Ch_LR; // capture has only one I2S pin, equals 2 channels. spdif is always 2 ch. } return RM_OK;}/** set up auto-detection of audio codec. if capturing from SPDIF, start audio passthrough to enable parsing of Pc/Pd values from stream *//* This function needs audio_opt for the audio playback */RMstatus start_detect_audio( struct cap_audio_instance *pAudio){ RMstatus err; struct AudioEngine_InputSPDIFStatus_type stat; RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->Setup.CaptureSource > 0) { if (! pAudio->pAudioSource) { // capture has not yet been set up, start the capture without playback to parse Pc/Pe from SPDIF stream RMDBGLOG((ENABLE, "\n\n\nStarting dummy audio capture (AC3)\n\n\n\n")); pAudio->cap_opt->Codec = AudioDecoder_Codec_AC3; err = cap_audio_start_passthrough(pAudio); } err = cap_audio_get_spdif_channel_status(pAudio, &stat); if (RMFAILED(err)) stat.Pc = 0; } else { // only LPCM on I2S stat.ChannelStatus = 0; stat.Pc = 0; } pAudio->auto_detect_codec = TRUE; err = cap_audio_get_codec_from_spdif_info(pAudio, &stat); if (RMSUCCEEDED(err) && (! pAudio->auto_detect_codec)) { pAudio->CurrChStat = stat.ChannelStatus; pAudio->CurrPc = stat.Pc; } return err;}/* transition to a new audio state, and perform the necessary actions of that transition */RMstatus cap_audio_set_state( struct cap_audio_instance *pAudio, enum audio_state audio_state){ RMstatus err = RM_OK; RMDBGLOG((FUNCNAME, "%s\n",__func__)); switch (audio_state) { case audio_state_off: // no audio present RMDBGLOG((ENABLE, " -- cap_audio_set_state( OFF )\n")); if (pAudio->audio_state != audio_state_off) { err = cap_audio_stop_passthrough(pAudio); } break; case audio_state_request: // start 200 mSec wait, check if audio is unstable during this wait RMDBGLOG((ENABLE, " -- cap_audio_set_state( WAIT )\n")); if (pAudio->audio_state == audio_state_on) { err = cap_audio_stop_passthrough(pAudio); } RMDBGLOG((ENABLE, "ACR PLL is presumed to be LOCKED\n")); pAudio->audio_pll_locked = TRUE; // might be set to FALSE by "PLL unlocked" interrupt during the 200 mSec, if PLL is unlocked pAudio->audio_guard_time = RMGetTimeInMicroSeconds(); break; case audio_state_on: // audio is stable and running RMDBGLOG((ENABLE, " -- cap_audio_set_state( ON )\n")); pAudio->audio_guard_time = RMGetTimeInMicroSeconds(); if (pAudio->audio_state != audio_state_on) { err = cap_audio_start_passthrough(pAudio); } break; } pAudio->audio_state = audio_state; return err;}/* handle steps of the audio state machine */RMstatus cap_audio_check_state( struct cap_audio_instance *pAudio){ RMstatus err = RM_OK; RMuint64 now; RMDBGLOG((FUNCNAME, "%s\n",__func__)); switch (pAudio->audio_state) { case audio_state_off: // no audio present //RMDBGLOG((ENABLE, " -- audio_state is ( OFF )\n")); break; case audio_state_request: // wait 200 mSec for stable audio //RMDBGLOG((ENABLE, " -- audio_state is ( WAIT )\n")); now = RMGetTimeInMicroSeconds(); if (RMCyclesElapsed64(pAudio->audio_guard_time, now) >= 200 * 1000) { if (pAudio->audio_pll_locked) { err = cap_audio_set_state(pAudio, audio_state_on); } else { err = cap_audio_set_state(pAudio, audio_state_request); } } break; case audio_state_on: // audio is stable and running //RMDBGLOG((ENABLE, " -- audio_state is ( ON )\n")); if (! pAudio->audio_pll_locked) { err = cap_audio_set_state(pAudio, audio_state_request); } break; } return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -