Merge pull request #90 from gizmo98/patch-2
[libretro-ppsspp.git] / Core / HW / SimpleAudioDec.cpp
blobc66e03e0790abb7d6f5adb31fab69c1e1c32d507
1 // Copyright (c) 2013- PPSSPP Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
18 #include <algorithm>
20 #include "Core/Config.h"
21 #include "Core/HLE/FunctionWrappers.h"
22 #include "Core/HW/SimpleAudioDec.h"
23 #include "Core/HW/MediaEngine.h"
24 #include "Core/HW/BufferQueue.h"
26 #ifdef USE_FFMPEG
28 extern "C" {
29 #include "libavformat/avformat.h"
30 #include "libswresample/swresample.h"
31 #include "libavutil/samplefmt.h"
34 #endif // USE_FFMPEG
36 int SimpleAudio::GetAudioCodecID(int audioType) {
37 #ifdef USE_FFMPEG
38 switch (audioType) {
39 case PSP_CODEC_AAC:
40 return AV_CODEC_ID_AAC;
41 case PSP_CODEC_AT3:
42 return AV_CODEC_ID_ATRAC3;
43 case PSP_CODEC_AT3PLUS:
44 return AV_CODEC_ID_ATRAC3P;
45 case PSP_CODEC_MP3:
46 return AV_CODEC_ID_MP3;
47 default:
48 return AV_CODEC_ID_NONE;
50 #else
51 return 0;
52 #endif // USE_FFMPEG
55 SimpleAudio::SimpleAudio(int audioType, int sample_rate, int channels)
56 : ctxPtr(0xFFFFFFFF), audioType(audioType), sample_rate_(sample_rate), channels_(channels),
57 outSamples(0), srcPos(0), wanted_resample_freq(44100), frame_(0), codec_(0), codecCtx_(0), swrCtx_(0),
58 extradata_(0), codecOpen_(false) {
59 Init();
62 void SimpleAudio::Init() {
63 #ifdef USE_FFMPEG
64 avcodec_register_all();
65 av_register_all();
66 InitFFmpeg();
68 frame_ = av_frame_alloc();
70 // Get Audio Codec ctx
71 int audioCodecId = GetAudioCodecID(audioType);
72 if (!audioCodecId) {
73 ERROR_LOG(ME, "This version of FFMPEG does not support Audio codec type: %08x. Update your submodule.", audioType);
74 return;
76 // Find decoder
77 codec_ = avcodec_find_decoder((AVCodecID)audioCodecId);
78 if (!codec_) {
79 // Eh, we shouldn't even have managed to compile. But meh.
80 ERROR_LOG(ME, "This version of FFMPEG does not support AV_CODEC_ctx for audio (%s). Update your submodule.", GetCodecName(audioType));
81 return;
83 // Allocate codec context
84 codecCtx_ = avcodec_alloc_context3(codec_);
85 if (!codecCtx_) {
86 ERROR_LOG(ME, "Failed to allocate a codec context");
87 return;
89 codecCtx_->channels = channels_;
90 codecCtx_->channel_layout = channels_ == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
91 codecCtx_->sample_rate = sample_rate_;
92 codecOpen_ = false;
93 #endif // USE_FFMPEG
96 bool SimpleAudio::OpenCodec(int block_align) {
97 #ifdef USE_FFMPEG
98 // Some versions of FFmpeg require this set. May be set in SetExtraData(), but optional.
99 // When decoding, we decode by packet, so we know the size.
100 if (codecCtx_->block_align == 0) {
101 codecCtx_->block_align = block_align;
104 AVDictionary *opts = 0;
105 int retval = avcodec_open2(codecCtx_, codec_, &opts);
106 if (retval < 0) {
107 ERROR_LOG(ME, "Failed to open codec: retval = %i", retval);
109 av_dict_free(&opts);
110 codecOpen_ = true;
111 return retval >= 0;
112 #else
113 return false;
114 #endif // USE_FFMPEG
117 bool SimpleAudio::ResetCodecCtx(int channels, int samplerate) {
118 #ifdef USE_FFMPEG
119 if (codecCtx_)
120 avcodec_close(codecCtx_);
122 // Find decoder
123 int audioCodecId = GetAudioCodecID(audioType);
124 codec_ = avcodec_find_decoder((AVCodecID)audioCodecId);
125 if (!codec_) {
126 // Eh, we shouldn't even have managed to compile. But meh.
127 ERROR_LOG(ME, "This version of FFMPEG does not support AV_CODEC_ctx for audio (%s). Update your submodule.", GetCodecName(audioType));
128 return false;
131 codecCtx_->channels = channels;
132 codecCtx_->channel_layout = channels==2?AV_CH_LAYOUT_STEREO:AV_CH_LAYOUT_MONO;
133 codecCtx_->sample_rate = samplerate;
134 codecOpen_ = false;
135 return true;
136 #endif
137 return false;
140 void SimpleAudio::SetExtraData(u8 *data, int size, int wav_bytes_per_packet) {
141 delete [] extradata_;
142 extradata_ = 0;
144 if (data != 0) {
145 extradata_ = new u8[size];
146 memcpy(extradata_, data, size);
149 #ifdef USE_FFMPEG
150 if (codecCtx_) {
151 codecCtx_->extradata = extradata_;
152 codecCtx_->extradata_size = size;
153 codecCtx_->block_align = wav_bytes_per_packet;
154 codecOpen_ = false;
156 #endif
159 SimpleAudio::~SimpleAudio() {
160 #ifdef USE_FFMPEG
161 if (swrCtx_)
162 swr_free(&swrCtx_);
163 if (frame_)
164 av_frame_free(&frame_);
165 if (codecCtx_)
166 avcodec_close(codecCtx_);
167 frame_ = 0;
168 codecCtx_ = 0;
169 codec_ = 0;
170 #endif // USE_FFMPEG
171 delete [] extradata_;
172 extradata_ = 0;
175 bool SimpleAudio::IsOK() const {
176 #ifdef USE_FFMPEG
177 return codec_ != 0;
178 #else
179 return 0;
180 #endif
183 bool SimpleAudio::Decode(void *inbuf, int inbytes, uint8_t *outbuf, int *outbytes) {
184 #ifdef USE_FFMPEG
185 if (!codecOpen_) {
186 OpenCodec(inbytes);
189 AVPacket packet;
190 av_init_packet(&packet);
191 packet.data = static_cast<uint8_t *>(inbuf);
192 packet.size = inbytes;
194 int got_frame = 0;
195 av_frame_unref(frame_);
197 *outbytes = 0;
198 srcPos = 0;
199 int len = avcodec_decode_audio4(codecCtx_, frame_, &got_frame, &packet);
200 if (len < 0) {
201 ERROR_LOG(ME, "Error decoding Audio frame (%i bytes): %i (%08x)", inbytes, len, len);
202 // TODO: cleanup
203 return false;
205 av_free_packet(&packet);
207 // get bytes consumed in source
208 srcPos = len;
210 if (got_frame) {
211 // Initializing the sample rate convert. We will use it to convert float output into int.
212 int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO; // we want stereo output layout
213 int64_t dec_channel_layout = frame_->channel_layout; // decoded channel layout
215 if (!swrCtx_) {
216 swrCtx_ = swr_alloc_set_opts(
217 swrCtx_,
218 wanted_channel_layout,
219 AV_SAMPLE_FMT_S16,
220 wanted_resample_freq,
221 dec_channel_layout,
222 codecCtx_->sample_fmt,
223 codecCtx_->sample_rate,
225 NULL);
227 if (!swrCtx_ || swr_init(swrCtx_) < 0) {
228 ERROR_LOG(ME, "swr_init: Failed to initialize the resampling context");
229 avcodec_close(codecCtx_);
230 codec_ = 0;
231 return false;
235 // convert audio to AV_SAMPLE_FMT_S16
236 int swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples);
237 if (swrRet < 0) {
238 ERROR_LOG(ME, "swr_convert: Error while converting: %d", swrRet);
239 return false;
241 // output samples per frame, we should *2 since we have two channels
242 outSamples = swrRet * 2;
244 // each sample occupies 2 bytes
245 *outbytes = outSamples * 2;
247 // Save outbuf into pcm audio, you can uncomment this line to save and check the decoded audio into pcm file.
248 // SaveAudio("dump.pcm", outbuf, *outbytes);
250 return true;
251 #else
252 // Zero bytes output. No need to memset.
253 *outbytes = 0;
254 return true;
255 #endif // USE_FFMPEG
258 int SimpleAudio::GetOutSamples() {
259 return outSamples;
262 int SimpleAudio::GetSourcePos() {
263 return srcPos;
266 void AudioClose(SimpleAudio **ctx) {
267 #ifdef USE_FFMPEG
268 delete *ctx;
269 *ctx = 0;
270 #endif // USE_FFMPEG
274 static const char *const codecNames[4] = {
275 "AT3+", "AT3", "MP3", "AAC",
278 const char *GetCodecName(int codec) {
279 if (codec >= PSP_CODEC_AT3PLUS && codec <= PSP_CODEC_AAC) {
280 return codecNames[codec - PSP_CODEC_AT3PLUS];
281 } else {
282 return "(unk)";
286 bool IsValidCodec(int codec){
287 if (codec >= PSP_CODEC_AT3PLUS && codec <= PSP_CODEC_AAC) {
288 return true;
290 return false;
294 // sceAu module starts from here
296 AuCtx::AuCtx() {
297 decoder = NULL;
298 startPos = 0;
299 endPos = 0;
300 LoopNum = -1;
301 AuBuf = 0;
302 AuBufSize = 2048;
303 PCMBuf = 0;
304 PCMBufSize = 2048;
305 AuBufAvailable = 0;
306 SamplingRate = 44100;
307 freq = SamplingRate;
308 BitRate = 0;
309 Channels = 2;
310 Version = 0;
311 SumDecodedSamples = 0;
312 MaxOutputSample = 0;
313 askedReadSize = 0;
314 realReadSize = 0;
315 audioType = 0;
316 FrameNum = 0;
319 AuCtx::~AuCtx(){
320 if (decoder){
321 AudioClose(&decoder);
322 decoder = NULL;
326 // return output pcm size, <0 error
327 u32 AuCtx::AuDecode(u32 pcmAddr)
329 if (!Memory::IsValidAddress(pcmAddr)){
330 ERROR_LOG(ME, "%s: output bufferAddress %08x is invalctx", __FUNCTION__, pcmAddr);
331 return -1;
334 auto outbuf = Memory::GetPointer(PCMBuf);
335 memset(outbuf, 0, PCMBufSize); // important! empty outbuf to avoid noise
336 u32 outpcmbufsize = 0;
338 int repeat = 1;
339 if (g_Config.bSoundSpeedHack){
340 repeat = 2;
342 int i = 0;
343 // decode frames in sourcebuff and output into PCMBuf (each time, we decode one or two frames)
344 // some games as Miku like one frame each time, some games like DOA like two frames each time
345 while (sourcebuff.size() > 0 && outpcmbufsize < PCMBufSize && i < repeat){
346 i++;
347 int pcmframesize;
348 // decode
349 decoder->Decode((void*)sourcebuff.c_str(), (int)sourcebuff.size(), outbuf, &pcmframesize);
350 if (pcmframesize == 0){
351 // no output pcm, we are at the end of the stream
352 AuBufAvailable = 0;
353 sourcebuff.clear();
354 if (LoopNum != 0){
355 // if we loop, reset readPos
356 readPos = startPos;
358 break;
360 // count total output pcm size
361 outpcmbufsize += pcmframesize;
362 // count total output samples
363 SumDecodedSamples += decoder->GetOutSamples();
364 // get consumed source length
365 int srcPos = decoder->GetSourcePos();
366 // remove the consumed source
367 sourcebuff.erase(0, srcPos);
368 // reduce the available Aubuff size
369 // (the available buff size is now used to know if we can read again from file and how many to read)
370 AuBufAvailable -= srcPos;
371 // move outbuff position to the current end of output
372 outbuf += pcmframesize;
373 // increase FrameNum count
374 FrameNum++;
376 Memory::Write_U32(PCMBuf, pcmAddr);
377 return outpcmbufsize;
380 u32 AuCtx::AuGetLoopNum()
382 return LoopNum;
385 u32 AuCtx::AuSetLoopNum(int loop)
387 LoopNum = loop;
388 return 0;
391 // return 1 to read more data stream, 0 don't read
392 int AuCtx::AuCheckStreamDataNeeded()
394 // if we have no available Au buffer, and the current read position in source file is not the end of stream, then we can read
395 if (AuBufAvailable < (int)AuBufSize && readPos < (int)endPos){
396 return 1;
398 return 0;
401 // check how many bytes we have read from source file
402 u32 AuCtx::AuNotifyAddStreamData(int size)
404 realReadSize = size;
405 int diffsize = realReadSize - askedReadSize;
406 // Notify the real read size
407 if (diffsize != 0){
408 readPos += diffsize;
409 AuBufAvailable += diffsize;
412 // append AuBuf into sourcebuff
413 sourcebuff.append((const char*)Memory::GetPointer(AuBuf), size);
415 if (readPos >= (int)endPos && LoopNum != 0){
416 // if we need loop, reset readPos
417 readPos = startPos;
418 // reset LoopNum
419 if (LoopNum > 0){
420 LoopNum--;
424 return 0;
427 // read from stream position srcPos of size bytes into buff
428 // buff, size and srcPos are all pointers
429 u32 AuCtx::AuGetInfoToAddStreamData(u32 buff, u32 size, u32 srcPos)
431 // you can not read beyond file size and the buffer size
432 int readsize = std::min((int)AuBufSize - AuBufAvailable, (int)endPos - readPos);
434 // we can recharge AuBuf from its beginning
435 if (Memory::IsValidAddress(buff))
436 Memory::Write_U32(AuBuf, buff);
437 if (Memory::IsValidAddress(size))
438 Memory::Write_U32(readsize, size);
439 if (Memory::IsValidAddress(srcPos))
440 Memory::Write_U32(readPos, srcPos);
442 // preset the readPos and available size, they will be notified later in NotifyAddStreamData.
443 askedReadSize = readsize;
444 readPos += askedReadSize;
445 AuBufAvailable += askedReadSize;
447 return 0;
450 u32 AuCtx::AuResetPlayPositionByFrame(int position) {
451 readPos = position;
452 return 0;
455 u32 AuCtx::AuResetPlayPosition() {
456 readPos = startPos;
457 return 0;
460 void AuCtx::DoState(PointerWrap &p) {
461 auto s = p.Section("AuContext", 0, 1);
462 if (!s)
463 return;
465 p.Do(startPos);
466 p.Do(endPos);
467 p.Do(AuBuf);
468 p.Do(AuBufSize);
469 p.Do(PCMBuf);
470 p.Do(PCMBufSize);
471 p.Do(freq);
472 p.Do(SumDecodedSamples);
473 p.Do(LoopNum);
474 p.Do(Channels);
475 p.Do(MaxOutputSample);
476 p.Do(readPos);
477 p.Do(audioType);
478 p.Do(BitRate);
479 p.Do(SamplingRate);
480 p.Do(askedReadSize);
481 p.Do(realReadSize);
482 p.Do(FrameNum);
484 if (p.mode == p.MODE_READ) {
485 decoder = new SimpleAudio(audioType);
486 AuBufAvailable = 0; // reset to read from file at position readPos