// Input is a single Atrac3+ packet. bool SimpleAT3::Decode(void* inbuf, int inbytes, uint8_t *outbuf, int *outbytes) { #ifdef USE_FFMPEG AVPacket packet = {0}; av_init_packet(&packet); packet.data = static_cast<uint8_t *>(inbuf); packet.size = inbytes; *outbytes = 0; int got_frame = 0; avcodec_get_frame_defaults(frame_); int len = avcodec_decode_audio4(codecCtx_, frame_, &got_frame, &packet); if (len < 0) { ERROR_LOG(ME, "Error decoding Atrac3+ frame"); // TODO: cleanup return false; } if (got_frame) { int data_size = av_samples_get_buffer_size( NULL, codecCtx_->channels, frame_->nb_samples, codecCtx_->sample_fmt, 1); int numSamples = frame_->nb_samples; int swrRet = swr_convert(swrCtx_, &outbuf, numSamples, (const u8 **)frame_->extended_data, numSamples); if (swrRet < 0) { ERROR_LOG(ME, "swr_convert: Error while converting %d", swrRet); return false; } // We always convert to stereo. __AdjustBGMVolume((s16 *)outbuf, numSamples * 2); } return true; #else // Zero bytes output. No need to memset. *outbytes = 0; return true; #endif // USE_FFMPEG }
bool SimpleAudio::Decode(void* inbuf, int inbytes, uint8_t *outbuf, int *outbytes) { #ifdef USE_FFMPEG AVPacket packet; av_init_packet(&packet); packet.data = static_cast<uint8_t *>(inbuf); packet.size = inbytes; int got_frame = 0; av_frame_unref(frame_); *outbytes = 0; srcPos = 0; int len = avcodec_decode_audio4(codecCtx_, frame_, &got_frame, &packet); if (len < 0) { ERROR_LOG(ME, "Error decoding Audio frame"); // TODO: cleanup return false; } av_free_packet(&packet); // get bytes consumed in source srcPos = len; if (got_frame) { // Initializing the sample rate convert. We will use it to convert float output into int. int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO; // we want stereo output layout int64_t dec_channel_layout = frame_->channel_layout; // decoded channel layout swrCtx_ = swr_alloc_set_opts( swrCtx_, wanted_channel_layout, AV_SAMPLE_FMT_S16, wanted_resample_freq, dec_channel_layout, codecCtx_->sample_fmt, codecCtx_->sample_rate, 0, NULL); if (!swrCtx_ || swr_init(swrCtx_) < 0) { ERROR_LOG(ME, "swr_init: Failed to initialize the resampling context"); avcodec_close(codecCtx_); codec_ = 0; return false; } // convert audio to AV_SAMPLE_FMT_S16 int swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples); if (swrRet < 0) { ERROR_LOG(ME, "swr_convert: Error while converting %d", swrRet); return false; } swr_free(&swrCtx_); // output samples per frame, we should *2 since we have two channels outSamples = swrRet * 2; // each sample occupies 2 bytes *outbytes = outSamples * 2; // We always convert to stereo. __AdjustBGMVolume((s16 *)outbuf, frame_->nb_samples * 2); // Save outbuf into pcm audio, you can uncomment this line to save and check the decoded audio into pcm file. // SaveAudio("dump.pcm", outbuf, *outbytes); } return true; #else // Zero bytes output. No need to memset. *outbytes = 0; return true; #endif // USE_FFMPEG }