Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/HW/SimpleAudioDec.cpp
5669 views
1
// Copyright (c) 2013- PPSSPP Project.
2
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.
6
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.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include <algorithm>
19
#include <cmath>
20
21
#include "Common/Serialize/SerializeFuncs.h"
22
#include "Core/Debugger/MemBlockInfo.h"
23
#include "Core/HLE/FunctionWrappers.h"
24
#include "Core/HW/SimpleAudioDec.h"
25
#include "Core/HW/MediaEngine.h"
26
#include "Core/HW/BufferQueue.h"
27
#include "Core/HW/Atrac3Standalone.h"
28
29
#include "ext/minimp3/minimp3.h"
30
31
#ifdef USE_FFMPEG
32
33
extern "C" {
34
#include "libavformat/avformat.h"
35
#include "libswresample/swresample.h"
36
#include "libavutil/samplefmt.h"
37
#include "libavcodec/avcodec.h"
38
#include "libavutil/version.h"
39
40
#include "Core/FFMPEGCompat.h"
41
}
42
#include "Core/Config.h"
43
44
#else
45
46
extern "C" {
47
struct AVCodec;
48
struct AVCodecContext;
49
struct SwrContext;
50
struct AVFrame;
51
}
52
53
#endif // USE_FFMPEG
54
55
// AAC decoder candidates:
56
// * https://github.com/mstorsjo/fdk-aac/tree/master
57
58
// h.264 decoder candidates:
59
// * https://github.com/meerkat-cv/h264_decoder
60
// * https://github.com/shengbinmeng/ffmpeg-h264-dec
61
62
// minimp3-based decoder.
63
class MiniMp3Audio : public AudioDecoder {
64
public:
65
MiniMp3Audio() {
66
mp3dec_init(&mp3_);
67
}
68
~MiniMp3Audio() {}
69
70
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) override {
71
_dbg_assert_(outputChannels == 2);
72
73
// When used from sceMp3LowLevelDecode, this fails to parse the mp3 header!
74
// It's because minimp3 is a bit more sensitive than ffmpeg - if you give it a buffer that's larger than the frame size,
75
// it'll check that there's a second matching frame before accepting. But in our case we only get one frame,
76
// but we do not know the size. So this might need some modifications in minimp3.
77
mp3dec_frame_info_t info{};
78
int samplesWritten = mp3dec_decode_frame(&mp3_, inbuf, inbytes, (mp3d_sample_t *)temp_, &info);
79
_dbg_assert_(samplesWritten <= MINIMP3_MAX_SAMPLES_PER_FRAME);
80
_dbg_assert_(info.channels <= 2);
81
if (info.channels == 1) {
82
for (int i = 0; i < samplesWritten; i++) {
83
outbuf[i * 2] = temp_[i];
84
outbuf[i * 2 + 1] = temp_[i];
85
}
86
} else {
87
memcpy(outbuf, temp_, 4 * samplesWritten);
88
}
89
*inbytesConsumed = info.frame_bytes;
90
*outSamples = samplesWritten;
91
return true;
92
}
93
94
bool IsOK() const override { return true; }
95
void SetChannels(int channels) override {
96
// Hmm. ignore for now.
97
}
98
99
PSPAudioType GetAudioType() const override { return PSP_CODEC_MP3; }
100
101
private:
102
// We use the lowest-level API.
103
mp3dec_t mp3_{};
104
int16_t temp_[MINIMP3_MAX_SAMPLES_PER_FRAME]{};
105
};
106
107
// FFMPEG-based decoder. TODO: Replace with individual codecs.
108
// Based on http://ffmpeg.org/doxygen/trunk/doc_2examples_2decoding_encoding_8c-example.html#_a13
109
class FFmpegAudioDecoder : public AudioDecoder {
110
public:
111
FFmpegAudioDecoder(PSPAudioType audioType, int sampleRateHz = 44100, int channels = 2);
112
~FFmpegAudioDecoder();
113
114
bool Decode(const uint8_t* inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) override;
115
bool IsOK() const override {
116
#ifdef USE_FFMPEG
117
return codec_ != 0;
118
#else
119
return 0;
120
#endif
121
}
122
123
void SetChannels(int channels) override;
124
125
// These two are only here because of save states.
126
PSPAudioType GetAudioType() const override { return audioType; }
127
128
private:
129
bool OpenCodec(int block_align);
130
131
PSPAudioType audioType;
132
int sample_rate_;
133
int channels_;
134
135
AVFrame *frame_ = nullptr;
136
AVCodec *codec_ = nullptr;
137
AVCodecContext *codecCtx_ = nullptr;
138
SwrContext *swrCtx_ = nullptr;
139
140
bool codecOpen_ = false;
141
};
142
143
AudioDecoder *CreateAudioDecoder(PSPAudioType audioType, int sampleRateHz, int channels, size_t blockAlign, const uint8_t *extraData, size_t extraDataSize) {
144
bool forceFfmpeg = false;
145
#ifdef USE_FFMPEG
146
forceFfmpeg = g_Config.bForceFfmpegForAudioDec;
147
#endif
148
if (forceFfmpeg) {
149
return new FFmpegAudioDecoder(audioType, sampleRateHz, channels);
150
}
151
152
switch (audioType) {
153
// Our MiniMP3 backend has too many issues:
154
// * Doesn't accept sample rate
155
// * Doesn't accept data where there's only one valid frame if the buffer is bigger.
156
// This prevents sceMp3LowLevelDecode from working, since nothing passes us the frame size.
157
//
158
// case PSP_CODEC_MP3:
159
// return new MiniMp3Audio();
160
case PSP_CODEC_AT3:
161
return CreateAtrac3Audio(channels, blockAlign, extraData, extraDataSize);
162
case PSP_CODEC_AT3PLUS:
163
return CreateAtrac3PlusAudio(channels, blockAlign);
164
default:
165
// Only AAC normally falls back to FFMPEG now.
166
return new FFmpegAudioDecoder(audioType, sampleRateHz, channels);
167
}
168
}
169
170
static int GetAudioCodecID(int audioType) {
171
#ifdef USE_FFMPEG
172
switch (audioType) {
173
case PSP_CODEC_AAC:
174
return AV_CODEC_ID_AAC;
175
case PSP_CODEC_AT3:
176
return AV_CODEC_ID_ATRAC3;
177
case PSP_CODEC_AT3PLUS:
178
return AV_CODEC_ID_ATRAC3P;
179
case PSP_CODEC_MP3:
180
return AV_CODEC_ID_MP3;
181
default:
182
return AV_CODEC_ID_NONE;
183
}
184
#else
185
return 0;
186
#endif // USE_FFMPEG
187
}
188
189
FFmpegAudioDecoder::FFmpegAudioDecoder(PSPAudioType audioType, int sampleRateHz, int channels)
190
: audioType(audioType), sample_rate_(sampleRateHz), channels_(channels) {
191
192
#ifdef USE_FFMPEG
193
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 18, 100)
194
avcodec_register_all();
195
#endif
196
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 12, 100)
197
av_register_all();
198
#endif
199
InitFFmpeg();
200
201
frame_ = av_frame_alloc();
202
203
// Get AUDIO Codec ctx
204
int audioCodecId = GetAudioCodecID(audioType);
205
if (!audioCodecId) {
206
ERROR_LOG(Log::ME, "This version of FFMPEG does not support Audio codec type: %08x. Update your submodule.", audioType);
207
return;
208
}
209
// Find decoder
210
codec_ = avcodec_find_decoder((AVCodecID)audioCodecId);
211
if (!codec_) {
212
// Eh, we shouldn't even have managed to compile. But meh.
213
ERROR_LOG(Log::ME, "This version of FFMPEG does not support AV_CODEC_ctx for audio (%s). Update your submodule.", GetCodecName(audioType));
214
return;
215
}
216
// Allocate codec context
217
codecCtx_ = avcodec_alloc_context3(codec_);
218
if (!codecCtx_) {
219
ERROR_LOG(Log::ME, "Found a decoder for audio codec ID %08x but failed to allocate a codec context. Strange.", audioCodecId);
220
return;
221
}
222
#if LIBAVUTIL_VERSION_MAJOR >= 59
223
if (channels_ == 2)
224
codecCtx_->ch_layout = AV_CHANNEL_LAYOUT_STEREO;
225
else
226
codecCtx_->ch_layout = AV_CHANNEL_LAYOUT_MONO;
227
#else
228
codecCtx_->channels = channels_;
229
codecCtx_->channel_layout = channels_ == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
230
#endif
231
codecCtx_->sample_rate = sample_rate_;
232
#endif // USE_FFMPEG
233
}
234
235
bool FFmpegAudioDecoder::OpenCodec(int block_align) {
236
#ifdef USE_FFMPEG
237
if (!codec_ || !codecCtx_) {
238
ERROR_LOG(Log::ME, "Codec context not allocated for some reason. This is bad.");
239
return false;
240
}
241
// Some versions of FFmpeg require this set. May be set in SetExtraData(), but optional.
242
// When decoding, we decode by packet, so we know the size.
243
if (codecCtx_->block_align == 0) {
244
codecCtx_->block_align = block_align;
245
}
246
247
AVDictionary *opts = 0;
248
int retval = avcodec_open2(codecCtx_, codec_, &opts);
249
if (retval < 0) {
250
ERROR_LOG(Log::ME, "Failed to open codec: retval = %i", retval);
251
}
252
av_dict_free(&opts);
253
codecOpen_ = true;
254
return retval >= 0;
255
#else
256
return false;
257
#endif // USE_FFMPEG
258
}
259
260
void FFmpegAudioDecoder::SetChannels(int channels) {
261
if (channels_ == channels) {
262
// Do nothing, already set.
263
return;
264
}
265
#ifdef USE_FFMPEG
266
267
if (codecOpen_) {
268
ERROR_LOG(Log::ME, "Codec already open, cannot change channels");
269
} else {
270
channels_ = channels;
271
#if LIBAVUTIL_VERSION_MAJOR >= 59
272
if (channels_ == 2)
273
codecCtx_->ch_layout = AV_CHANNEL_LAYOUT_STEREO;
274
else
275
codecCtx_->ch_layout = AV_CHANNEL_LAYOUT_MONO;
276
#else
277
codecCtx_->channels = channels_;
278
codecCtx_->channel_layout = channels_ == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
279
#endif
280
}
281
#endif
282
}
283
284
FFmpegAudioDecoder::~FFmpegAudioDecoder() {
285
#ifdef USE_FFMPEG
286
swr_free(&swrCtx_);
287
av_frame_free(&frame_);
288
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0)
289
avcodec_free_context(&codecCtx_);
290
#else
291
// Future versions may add other things to free, but avcodec_free_context didn't exist yet here.
292
avcodec_close(codecCtx_);
293
av_freep(&codecCtx_->extradata);
294
av_freep(&codecCtx_->subtitle_header);
295
av_freep(&codecCtx_);
296
#endif
297
codec_ = 0;
298
#endif // USE_FFMPEG
299
}
300
301
// Decodes a single input frame.
302
bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) {
303
#ifdef USE_FFMPEG
304
if (!codecOpen_) {
305
OpenCodec(inbytes);
306
if (!codecOpen_) {
307
ERROR_LOG(Log::ME, "Codec not open, can't decode.");
308
return false;
309
}
310
}
311
312
AVPacket packet;
313
av_init_packet(&packet);
314
packet.data = (uint8_t *)(inbuf);
315
packet.size = inbytes;
316
317
int got_frame = 0;
318
av_frame_unref(frame_);
319
320
if (outSamples) {
321
*outSamples = 0;
322
}
323
if (inbytesConsumed) {
324
*inbytesConsumed = 0;
325
}
326
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
327
if (inbytes != 0) {
328
int err = avcodec_send_packet(codecCtx_, &packet);
329
if (err < 0) {
330
ERROR_LOG(Log::ME, "Error sending audio frame to decoder (%d bytes): %d (%08x)", inbytes, err, err);
331
return false;
332
}
333
}
334
int err = avcodec_receive_frame(codecCtx_, frame_);
335
int len = 0;
336
if (err >= 0) {
337
len = packet.size;
338
got_frame = 1;
339
} else if (err != AVERROR(EAGAIN)) {
340
len = err;
341
}
342
#else
343
int len = avcodec_decode_audio4(codecCtx_, frame_, &got_frame, &packet);
344
#endif
345
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
346
av_packet_unref(&packet);
347
#else
348
av_free_packet(&packet);
349
#endif
350
351
if (len < 0) {
352
ERROR_LOG(Log::ME, "Error decoding Audio frame (%i bytes): %i (%08x)", inbytes, len, len);
353
return false;
354
}
355
356
// get bytes consumed in source
357
if (inbytesConsumed) {
358
*inbytesConsumed = len;
359
}
360
361
if (got_frame) {
362
// Initializing the sample rate convert. We will use it to convert float output into int.
363
_dbg_assert_(outputChannels == 2);
364
#if LIBAVUTIL_VERSION_MAJOR >= 59
365
AVChannelLayout wanted_channel_layout = AV_CHANNEL_LAYOUT_STEREO; // we want stereo output layout
366
const AVChannelLayout& dec_channel_layout = frame_->ch_layout; // decoded channel layout
367
#else
368
int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO; // we want stereo output layout
369
int64_t dec_channel_layout = frame_->channel_layout; // decoded channel layout
370
#endif
371
372
if (!swrCtx_) {
373
// TODO: Allow these to differ.
374
const int inputSampleRate = codecCtx_->sample_rate;
375
const int outputSampleRate = codecCtx_->sample_rate;
376
#if LIBAVUTIL_VERSION_MAJOR >= 59
377
swr_alloc_set_opts2(
378
&swrCtx_,
379
&wanted_channel_layout,
380
AV_SAMPLE_FMT_S16,
381
outputSampleRate,
382
&dec_channel_layout,
383
codecCtx_->sample_fmt,
384
inputSampleRate,
385
0,
386
NULL);
387
#else
388
swrCtx_ = swr_alloc_set_opts(
389
swrCtx_,
390
wanted_channel_layout,
391
AV_SAMPLE_FMT_S16,
392
outputSampleRate,
393
dec_channel_layout,
394
codecCtx_->sample_fmt,
395
inputSampleRate,
396
0,
397
NULL);
398
#endif
399
400
if (!swrCtx_ || swr_init(swrCtx_) < 0) {
401
ERROR_LOG(Log::ME, "swr_init: Failed to initialize the resampling context");
402
#if LIBAVCODEC_VERSION_MAJOR >= 62
403
avcodec_free_context(&codecCtx_);
404
#else
405
avcodec_close(codecCtx_);
406
#endif
407
codec_ = 0;
408
return false;
409
}
410
}
411
412
// convert audio to AV_SAMPLE_FMT_S16
413
int swrRet = 0;
414
if (outbuf != nullptr) {
415
swrRet = swr_convert(swrCtx_, (uint8_t **)&outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples);
416
}
417
if (swrRet < 0) {
418
ERROR_LOG(Log::ME, "swr_convert: Error while converting: %d", swrRet);
419
return false;
420
}
421
// output stereo samples per frame
422
if (outSamples) {
423
*outSamples = swrRet;
424
}
425
426
// Save outbuf into pcm audio, you can uncomment this line to save and check the decoded audio into pcm file.
427
// SaveAudio("dump.pcm", outbuf, *outbytes);
428
}
429
return true;
430
#else
431
// Zero bytes output. No need to memset.
432
*outSamples = 0;
433
return true;
434
#endif // USE_FFMPEG
435
}
436
437
void AudioClose(AudioDecoder **ctx) {
438
#ifdef USE_FFMPEG
439
delete *ctx;
440
*ctx = 0;
441
#endif // USE_FFMPEG
442
}
443
444
void AudioClose(FFmpegAudioDecoder **ctx) {
445
#ifdef USE_FFMPEG
446
delete *ctx;
447
*ctx = 0;
448
#endif // USE_FFMPEG
449
}
450
451
static const char *const codecNames[4] = {
452
"AT3+", "AT3", "MP3", "AAC",
453
};
454
455
const char *GetCodecName(int codec) {
456
if (codec >= PSP_CODEC_AT3PLUS && codec <= PSP_CODEC_AAC) {
457
return codecNames[codec - PSP_CODEC_AT3PLUS];
458
} else {
459
return "(unk)";
460
}
461
};
462
463
bool IsValidCodec(PSPAudioType codec){
464
if (codec >= PSP_CODEC_AT3PLUS && codec <= PSP_CODEC_AAC) {
465
return true;
466
}
467
return false;
468
}
469
470
471
// sceAu module starts from here
472
473
AuCtx::AuCtx() {
474
}
475
476
AuCtx::~AuCtx() {
477
if (decoder) {
478
AudioClose(&decoder);
479
decoder = nullptr;
480
}
481
}
482
483
size_t AuCtx::FindNextMp3Sync() {
484
for (size_t i = 0; i < sourcebuff.size() - 2; ++i) {
485
if ((sourcebuff[i] & 0xFF) == 0xFF && (sourcebuff[i + 1] & 0xC0) == 0xC0) {
486
return i;
487
}
488
}
489
return 0;
490
}
491
492
// return output pcm size, <0 error
493
u32 AuCtx::AuDecode(u32 pcmAddr) {
494
u32 outptr = PCMBuf + nextOutputHalf * PCMBufSize / 2;
495
auto outbuf = Memory::GetPointerWriteRange(outptr, PCMBufSize / 2);
496
int outpcmbufsize = 0;
497
498
if (pcmAddr)
499
Memory::Write_U32(outptr, pcmAddr);
500
501
// Decode a single frame in sourcebuff and output into PCMBuf.
502
if (!sourcebuff.empty()) {
503
// FFmpeg doesn't seem to search for a sync for us, so let's do that.
504
int nextSync = 0;
505
if (decoder->GetAudioType() == PSP_CODEC_MP3) {
506
nextSync = (int)FindNextMp3Sync();
507
}
508
int inbytesConsumed = 0;
509
int outSamples = 0;
510
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, &inbytesConsumed, 2, (int16_t *)outbuf, &outSamples);
511
outpcmbufsize = outSamples * 2 * sizeof(int16_t);
512
513
if (outpcmbufsize == 0) {
514
// Nothing was output, hopefully we're at the end of the stream.
515
AuBufAvailable = 0;
516
sourcebuff.clear();
517
} else {
518
// Update our total decoded samples, but don't count stereo.
519
SumDecodedSamples += outSamples;
520
// get consumed source length
521
int srcPos = inbytesConsumed + nextSync;
522
// remove the consumed source
523
if (srcPos > 0)
524
sourcebuff.erase(sourcebuff.begin(), sourcebuff.begin() + srcPos);
525
// reduce the available Aubuff size
526
// (the available buff size is now used to know if we can read again from file and how many to read)
527
AuBufAvailable -= srcPos;
528
}
529
}
530
531
bool end = readPos - AuBufAvailable >= (int64_t)endPos;
532
if (end && LoopNum != 0) {
533
// When looping, start the sum back off at zero and reset readPos to the start.
534
SumDecodedSamples = 0;
535
readPos = startPos;
536
if (LoopNum > 0)
537
LoopNum--;
538
}
539
540
if (outpcmbufsize == 0 && !end) {
541
// If we didn't decode anything, we fill this half of the buffer with zeros.
542
outpcmbufsize = PCMBufSize / 2;
543
if (outbuf != nullptr)
544
memset(outbuf, 0, outpcmbufsize);
545
} else if ((u32)outpcmbufsize < PCMBufSize) {
546
// TODO: Not sure it actually zeros this out.
547
if (outbuf != nullptr)
548
memset(outbuf + outpcmbufsize, 0, PCMBufSize / 2 - outpcmbufsize);
549
}
550
551
if (outpcmbufsize != 0)
552
NotifyMemInfo(MemBlockFlags::WRITE, outptr, outpcmbufsize, "AuDecode");
553
554
nextOutputHalf ^= 1;
555
return outpcmbufsize;
556
}
557
558
// return 1 to read more data stream, 0 don't read
559
int AuCtx::AuCheckStreamDataNeeded() {
560
// If we would ask for bytes, then some are needed.
561
if (AuStreamBytesNeeded() > 0) {
562
return 1;
563
}
564
return 0;
565
}
566
567
int AuCtx::AuStreamBytesNeeded() {
568
if (decoder->GetAudioType() == PSP_CODEC_MP3) {
569
// The endPos and readPos are not considered, except when you've read to the end.
570
if (readPos >= endPos)
571
return 0;
572
// Account for the workarea.
573
int offset = AuStreamWorkareaSize();
574
return (int)AuBufSize - AuBufAvailable - offset;
575
}
576
577
// TODO: Untested. Maybe similar to MP3.
578
return std::min((int)AuBufSize - AuBufAvailable, (int)endPos - readPos);
579
}
580
581
int AuCtx::AuStreamWorkareaSize() {
582
// Note that this is 31 bytes more than the max layer 3 frame size.
583
if (decoder->GetAudioType() == PSP_CODEC_MP3)
584
return 0x05c0;
585
return 0;
586
}
587
588
// check how many bytes we have read from source file
589
u32 AuCtx::AuNotifyAddStreamData(int size) {
590
int offset = AuStreamWorkareaSize();
591
592
if (askedReadSize != 0) {
593
// Old save state, numbers already adjusted.
594
int diffsize = size - askedReadSize;
595
// Notify the real read size
596
if (diffsize != 0) {
597
readPos += diffsize;
598
AuBufAvailable += diffsize;
599
}
600
askedReadSize = 0;
601
} else {
602
readPos += size;
603
AuBufAvailable += size;
604
}
605
606
if (Memory::IsValidRange(AuBuf, size)) {
607
sourcebuff.resize(sourcebuff.size() + size);
608
Memory::MemcpyUnchecked(&sourcebuff[sourcebuff.size() - size], AuBuf + offset, size);
609
}
610
611
return 0;
612
}
613
614
// read from stream position srcPos of size bytes into buff
615
// buff, size and srcPos are all pointers
616
u32 AuCtx::AuGetInfoToAddStreamData(u32 bufPtr, u32 sizePtr, u32 srcPosPtr) {
617
int readsize = AuStreamBytesNeeded();
618
int offset = AuStreamWorkareaSize();
619
620
// we can recharge AuBuf from its beginning
621
if (readsize != 0) {
622
if (Memory::IsValidAddress(bufPtr))
623
Memory::WriteUnchecked_U32(AuBuf + offset, bufPtr);
624
if (Memory::IsValidAddress(sizePtr))
625
Memory::WriteUnchecked_U32(readsize, sizePtr);
626
if (Memory::IsValidAddress(srcPosPtr))
627
Memory::WriteUnchecked_U32(readPos, srcPosPtr);
628
} else {
629
if (Memory::IsValidAddress(bufPtr))
630
Memory::WriteUnchecked_U32(0, bufPtr);
631
if (Memory::IsValidAddress(sizePtr))
632
Memory::WriteUnchecked_U32(0, sizePtr);
633
if (Memory::IsValidAddress(srcPosPtr))
634
Memory::WriteUnchecked_U32(0, srcPosPtr);
635
}
636
637
// Just for old save states.
638
askedReadSize = 0;
639
return 0;
640
}
641
642
u32 AuCtx::AuResetPlayPositionByFrame(int frame) {
643
// Note: this doesn't correctly handle padding or slot size, but the PSP doesn't either.
644
uint32_t bytesPerSecond = (MaxOutputSample / 8) * BitRate * 1000;
645
readPos = startPos + (frame * bytesPerSecond) / SamplingRate;
646
// Not sure why, but it seems to consistently seek 1 before, maybe in case it's off slightly.
647
if (frame != 0)
648
readPos -= 1;
649
SumDecodedSamples = frame * MaxOutputSample;
650
AuBufAvailable = 0;
651
sourcebuff.clear();
652
return 0;
653
}
654
655
u32 AuCtx::AuResetPlayPosition() {
656
readPos = startPos;
657
SumDecodedSamples = 0;
658
AuBufAvailable = 0;
659
sourcebuff.clear();
660
return 0;
661
}
662
663
void AuCtx::DoState(PointerWrap &p) {
664
auto s = p.Section("AuContext", 0, 2);
665
if (!s)
666
return;
667
668
Do(p, startPos);
669
Do(p, endPos);
670
Do(p, AuBuf);
671
Do(p, AuBufSize);
672
Do(p, PCMBuf);
673
Do(p, PCMBufSize);
674
Do(p, freq);
675
Do(p, SumDecodedSamples);
676
Do(p, LoopNum);
677
Do(p, Channels);
678
Do(p, MaxOutputSample);
679
Do(p, readPos);
680
int audioType = decoder ? (int)decoder->GetAudioType() : 0;
681
Do(p, audioType);
682
Do(p, BitRate);
683
Do(p, SamplingRate);
684
Do(p, askedReadSize);
685
int dummy = 0;
686
Do(p, dummy);
687
Do(p, FrameNum);
688
689
if (s < 2) {
690
AuBufAvailable = 0;
691
Version = 3;
692
} else {
693
Do(p, Version);
694
Do(p, AuBufAvailable);
695
Do(p, sourcebuff);
696
Do(p, nextOutputHalf);
697
}
698
699
if (p.mode == p.MODE_READ) {
700
decoder = CreateAudioDecoder((PSPAudioType)audioType);
701
}
702
}
703
704