Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/HW/SimpleAudioDec.cpp
3186 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, "Failed to allocate a codec context");
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
codecOpen_ = false;
233
#endif // USE_FFMPEG
234
}
235
236
bool FFmpegAudioDecoder::OpenCodec(int block_align) {
237
#ifdef USE_FFMPEG
238
// Some versions of FFmpeg require this set. May be set in SetExtraData(), but optional.
239
// When decoding, we decode by packet, so we know the size.
240
if (codecCtx_->block_align == 0) {
241
codecCtx_->block_align = block_align;
242
}
243
244
AVDictionary *opts = 0;
245
int retval = avcodec_open2(codecCtx_, codec_, &opts);
246
if (retval < 0) {
247
ERROR_LOG(Log::ME, "Failed to open codec: retval = %i", retval);
248
}
249
av_dict_free(&opts);
250
codecOpen_ = true;
251
return retval >= 0;
252
#else
253
return false;
254
#endif // USE_FFMPEG
255
}
256
257
void FFmpegAudioDecoder::SetChannels(int channels) {
258
if (channels_ == channels) {
259
// Do nothing, already set.
260
return;
261
}
262
#ifdef USE_FFMPEG
263
264
if (codecOpen_) {
265
ERROR_LOG(Log::ME, "Codec already open, cannot change channels");
266
} else {
267
channels_ = channels;
268
#if LIBAVUTIL_VERSION_MAJOR >= 59
269
if (channels_ == 2)
270
codecCtx_->ch_layout = AV_CHANNEL_LAYOUT_STEREO;
271
else
272
codecCtx_->ch_layout = AV_CHANNEL_LAYOUT_MONO;
273
#else
274
codecCtx_->channels = channels_;
275
codecCtx_->channel_layout = channels_ == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
276
#endif
277
}
278
#endif
279
}
280
281
FFmpegAudioDecoder::~FFmpegAudioDecoder() {
282
#ifdef USE_FFMPEG
283
swr_free(&swrCtx_);
284
av_frame_free(&frame_);
285
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0)
286
avcodec_free_context(&codecCtx_);
287
#else
288
// Future versions may add other things to free, but avcodec_free_context didn't exist yet here.
289
avcodec_close(codecCtx_);
290
av_freep(&codecCtx_->extradata);
291
av_freep(&codecCtx_->subtitle_header);
292
av_freep(&codecCtx_);
293
#endif
294
codec_ = 0;
295
#endif // USE_FFMPEG
296
}
297
298
// Decodes a single input frame.
299
bool FFmpegAudioDecoder::Decode(const uint8_t *inbuf, int inbytes, int *inbytesConsumed, int outputChannels, int16_t *outbuf, int *outSamples) {
300
#ifdef USE_FFMPEG
301
if (!codecOpen_) {
302
OpenCodec(inbytes);
303
}
304
305
AVPacket packet;
306
av_init_packet(&packet);
307
packet.data = (uint8_t *)(inbuf);
308
packet.size = inbytes;
309
310
int got_frame = 0;
311
av_frame_unref(frame_);
312
313
if (outSamples) {
314
*outSamples = 0;
315
}
316
if (inbytesConsumed) {
317
*inbytesConsumed = 0;
318
}
319
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
320
if (inbytes != 0) {
321
int err = avcodec_send_packet(codecCtx_, &packet);
322
if (err < 0) {
323
ERROR_LOG(Log::ME, "Error sending audio frame to decoder (%d bytes): %d (%08x)", inbytes, err, err);
324
return false;
325
}
326
}
327
int err = avcodec_receive_frame(codecCtx_, frame_);
328
int len = 0;
329
if (err >= 0) {
330
len = frame_->pkt_size;
331
got_frame = 1;
332
} else if (err != AVERROR(EAGAIN)) {
333
len = err;
334
}
335
#else
336
int len = avcodec_decode_audio4(codecCtx_, frame_, &got_frame, &packet);
337
#endif
338
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
339
av_packet_unref(&packet);
340
#else
341
av_free_packet(&packet);
342
#endif
343
344
if (len < 0) {
345
ERROR_LOG(Log::ME, "Error decoding Audio frame (%i bytes): %i (%08x)", inbytes, len, len);
346
return false;
347
}
348
349
// get bytes consumed in source
350
if (inbytesConsumed) {
351
*inbytesConsumed = len;
352
}
353
354
if (got_frame) {
355
// Initializing the sample rate convert. We will use it to convert float output into int.
356
_dbg_assert_(outputChannels == 2);
357
#if LIBAVUTIL_VERSION_MAJOR >= 59
358
AVChannelLayout wanted_channel_layout = AV_CHANNEL_LAYOUT_STEREO; // we want stereo output layout
359
const AVChannelLayout& dec_channel_layout = frame_->ch_layout; // decoded channel layout
360
#else
361
int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO; // we want stereo output layout
362
int64_t dec_channel_layout = frame_->channel_layout; // decoded channel layout
363
#endif
364
365
if (!swrCtx_) {
366
// TODO: Allow these to differ.
367
const int inputSampleRate = codecCtx_->sample_rate;
368
const int outputSampleRate = codecCtx_->sample_rate;
369
#if LIBAVUTIL_VERSION_MAJOR >= 59
370
swr_alloc_set_opts2(
371
&swrCtx_,
372
&wanted_channel_layout,
373
AV_SAMPLE_FMT_S16,
374
outputSampleRate,
375
&dec_channel_layout,
376
codecCtx_->sample_fmt,
377
inputSampleRate,
378
0,
379
NULL);
380
#else
381
swrCtx_ = swr_alloc_set_opts(
382
swrCtx_,
383
wanted_channel_layout,
384
AV_SAMPLE_FMT_S16,
385
outputSampleRate,
386
dec_channel_layout,
387
codecCtx_->sample_fmt,
388
inputSampleRate,
389
0,
390
NULL);
391
#endif
392
393
if (!swrCtx_ || swr_init(swrCtx_) < 0) {
394
ERROR_LOG(Log::ME, "swr_init: Failed to initialize the resampling context");
395
avcodec_close(codecCtx_);
396
codec_ = 0;
397
return false;
398
}
399
}
400
401
// convert audio to AV_SAMPLE_FMT_S16
402
int swrRet = 0;
403
if (outbuf != nullptr) {
404
swrRet = swr_convert(swrCtx_, (uint8_t **)&outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples);
405
}
406
if (swrRet < 0) {
407
ERROR_LOG(Log::ME, "swr_convert: Error while converting: %d", swrRet);
408
return false;
409
}
410
// output stereo samples per frame
411
if (outSamples) {
412
*outSamples = swrRet;
413
}
414
415
// Save outbuf into pcm audio, you can uncomment this line to save and check the decoded audio into pcm file.
416
// SaveAudio("dump.pcm", outbuf, *outbytes);
417
}
418
return true;
419
#else
420
// Zero bytes output. No need to memset.
421
*outSamples = 0;
422
return true;
423
#endif // USE_FFMPEG
424
}
425
426
void AudioClose(AudioDecoder **ctx) {
427
#ifdef USE_FFMPEG
428
delete *ctx;
429
*ctx = 0;
430
#endif // USE_FFMPEG
431
}
432
433
void AudioClose(FFmpegAudioDecoder **ctx) {
434
#ifdef USE_FFMPEG
435
delete *ctx;
436
*ctx = 0;
437
#endif // USE_FFMPEG
438
}
439
440
static const char *const codecNames[4] = {
441
"AT3+", "AT3", "MP3", "AAC",
442
};
443
444
const char *GetCodecName(int codec) {
445
if (codec >= PSP_CODEC_AT3PLUS && codec <= PSP_CODEC_AAC) {
446
return codecNames[codec - PSP_CODEC_AT3PLUS];
447
} else {
448
return "(unk)";
449
}
450
};
451
452
bool IsValidCodec(PSPAudioType codec){
453
if (codec >= PSP_CODEC_AT3PLUS && codec <= PSP_CODEC_AAC) {
454
return true;
455
}
456
return false;
457
}
458
459
460
// sceAu module starts from here
461
462
AuCtx::AuCtx() {
463
}
464
465
AuCtx::~AuCtx() {
466
if (decoder) {
467
AudioClose(&decoder);
468
decoder = nullptr;
469
}
470
}
471
472
size_t AuCtx::FindNextMp3Sync() {
473
for (size_t i = 0; i < sourcebuff.size() - 2; ++i) {
474
if ((sourcebuff[i] & 0xFF) == 0xFF && (sourcebuff[i + 1] & 0xC0) == 0xC0) {
475
return i;
476
}
477
}
478
return 0;
479
}
480
481
// return output pcm size, <0 error
482
u32 AuCtx::AuDecode(u32 pcmAddr) {
483
u32 outptr = PCMBuf + nextOutputHalf * PCMBufSize / 2;
484
auto outbuf = Memory::GetPointerWriteRange(outptr, PCMBufSize / 2);
485
int outpcmbufsize = 0;
486
487
if (pcmAddr)
488
Memory::Write_U32(outptr, pcmAddr);
489
490
// Decode a single frame in sourcebuff and output into PCMBuf.
491
if (!sourcebuff.empty()) {
492
// FFmpeg doesn't seem to search for a sync for us, so let's do that.
493
int nextSync = 0;
494
if (decoder->GetAudioType() == PSP_CODEC_MP3) {
495
nextSync = (int)FindNextMp3Sync();
496
}
497
int inbytesConsumed = 0;
498
int outSamples = 0;
499
decoder->Decode(&sourcebuff[nextSync], (int)sourcebuff.size() - nextSync, &inbytesConsumed, 2, (int16_t *)outbuf, &outSamples);
500
outpcmbufsize = outSamples * 2 * sizeof(int16_t);
501
502
if (outpcmbufsize == 0) {
503
// Nothing was output, hopefully we're at the end of the stream.
504
AuBufAvailable = 0;
505
sourcebuff.clear();
506
} else {
507
// Update our total decoded samples, but don't count stereo.
508
SumDecodedSamples += outSamples;
509
// get consumed source length
510
int srcPos = inbytesConsumed + nextSync;
511
// remove the consumed source
512
if (srcPos > 0)
513
sourcebuff.erase(sourcebuff.begin(), sourcebuff.begin() + srcPos);
514
// reduce the available Aubuff size
515
// (the available buff size is now used to know if we can read again from file and how many to read)
516
AuBufAvailable -= srcPos;
517
}
518
}
519
520
bool end = readPos - AuBufAvailable >= (int64_t)endPos;
521
if (end && LoopNum != 0) {
522
// When looping, start the sum back off at zero and reset readPos to the start.
523
SumDecodedSamples = 0;
524
readPos = startPos;
525
if (LoopNum > 0)
526
LoopNum--;
527
}
528
529
if (outpcmbufsize == 0 && !end) {
530
// If we didn't decode anything, we fill this half of the buffer with zeros.
531
outpcmbufsize = PCMBufSize / 2;
532
if (outbuf != nullptr)
533
memset(outbuf, 0, outpcmbufsize);
534
} else if ((u32)outpcmbufsize < PCMBufSize) {
535
// TODO: Not sure it actually zeros this out.
536
if (outbuf != nullptr)
537
memset(outbuf + outpcmbufsize, 0, PCMBufSize / 2 - outpcmbufsize);
538
}
539
540
if (outpcmbufsize != 0)
541
NotifyMemInfo(MemBlockFlags::WRITE, outptr, outpcmbufsize, "AuDecode");
542
543
nextOutputHalf ^= 1;
544
return outpcmbufsize;
545
}
546
547
// return 1 to read more data stream, 0 don't read
548
int AuCtx::AuCheckStreamDataNeeded() {
549
// If we would ask for bytes, then some are needed.
550
if (AuStreamBytesNeeded() > 0) {
551
return 1;
552
}
553
return 0;
554
}
555
556
int AuCtx::AuStreamBytesNeeded() {
557
if (decoder->GetAudioType() == PSP_CODEC_MP3) {
558
// The endPos and readPos are not considered, except when you've read to the end.
559
if (readPos >= endPos)
560
return 0;
561
// Account for the workarea.
562
int offset = AuStreamWorkareaSize();
563
return (int)AuBufSize - AuBufAvailable - offset;
564
}
565
566
// TODO: Untested. Maybe similar to MP3.
567
return std::min((int)AuBufSize - AuBufAvailable, (int)endPos - readPos);
568
}
569
570
int AuCtx::AuStreamWorkareaSize() {
571
// Note that this is 31 bytes more than the max layer 3 frame size.
572
if (decoder->GetAudioType() == PSP_CODEC_MP3)
573
return 0x05c0;
574
return 0;
575
}
576
577
// check how many bytes we have read from source file
578
u32 AuCtx::AuNotifyAddStreamData(int size) {
579
int offset = AuStreamWorkareaSize();
580
581
if (askedReadSize != 0) {
582
// Old save state, numbers already adjusted.
583
int diffsize = size - askedReadSize;
584
// Notify the real read size
585
if (diffsize != 0) {
586
readPos += diffsize;
587
AuBufAvailable += diffsize;
588
}
589
askedReadSize = 0;
590
} else {
591
readPos += size;
592
AuBufAvailable += size;
593
}
594
595
if (Memory::IsValidRange(AuBuf, size)) {
596
sourcebuff.resize(sourcebuff.size() + size);
597
Memory::MemcpyUnchecked(&sourcebuff[sourcebuff.size() - size], AuBuf + offset, size);
598
}
599
600
return 0;
601
}
602
603
// read from stream position srcPos of size bytes into buff
604
// buff, size and srcPos are all pointers
605
u32 AuCtx::AuGetInfoToAddStreamData(u32 bufPtr, u32 sizePtr, u32 srcPosPtr) {
606
int readsize = AuStreamBytesNeeded();
607
int offset = AuStreamWorkareaSize();
608
609
// we can recharge AuBuf from its beginning
610
if (readsize != 0) {
611
if (Memory::IsValidAddress(bufPtr))
612
Memory::WriteUnchecked_U32(AuBuf + offset, bufPtr);
613
if (Memory::IsValidAddress(sizePtr))
614
Memory::WriteUnchecked_U32(readsize, sizePtr);
615
if (Memory::IsValidAddress(srcPosPtr))
616
Memory::WriteUnchecked_U32(readPos, srcPosPtr);
617
} else {
618
if (Memory::IsValidAddress(bufPtr))
619
Memory::WriteUnchecked_U32(0, bufPtr);
620
if (Memory::IsValidAddress(sizePtr))
621
Memory::WriteUnchecked_U32(0, sizePtr);
622
if (Memory::IsValidAddress(srcPosPtr))
623
Memory::WriteUnchecked_U32(0, srcPosPtr);
624
}
625
626
// Just for old save states.
627
askedReadSize = 0;
628
return 0;
629
}
630
631
u32 AuCtx::AuResetPlayPositionByFrame(int frame) {
632
// Note: this doesn't correctly handle padding or slot size, but the PSP doesn't either.
633
uint32_t bytesPerSecond = (MaxOutputSample / 8) * BitRate * 1000;
634
readPos = startPos + (frame * bytesPerSecond) / SamplingRate;
635
// Not sure why, but it seems to consistently seek 1 before, maybe in case it's off slightly.
636
if (frame != 0)
637
readPos -= 1;
638
SumDecodedSamples = frame * MaxOutputSample;
639
AuBufAvailable = 0;
640
sourcebuff.clear();
641
return 0;
642
}
643
644
u32 AuCtx::AuResetPlayPosition() {
645
readPos = startPos;
646
SumDecodedSamples = 0;
647
AuBufAvailable = 0;
648
sourcebuff.clear();
649
return 0;
650
}
651
652
void AuCtx::DoState(PointerWrap &p) {
653
auto s = p.Section("AuContext", 0, 2);
654
if (!s)
655
return;
656
657
Do(p, startPos);
658
Do(p, endPos);
659
Do(p, AuBuf);
660
Do(p, AuBufSize);
661
Do(p, PCMBuf);
662
Do(p, PCMBufSize);
663
Do(p, freq);
664
Do(p, SumDecodedSamples);
665
Do(p, LoopNum);
666
Do(p, Channels);
667
Do(p, MaxOutputSample);
668
Do(p, readPos);
669
int audioType = decoder ? (int)decoder->GetAudioType() : 0;
670
Do(p, audioType);
671
Do(p, BitRate);
672
Do(p, SamplingRate);
673
Do(p, askedReadSize);
674
int dummy = 0;
675
Do(p, dummy);
676
Do(p, FrameNum);
677
678
if (s < 2) {
679
AuBufAvailable = 0;
680
Version = 3;
681
} else {
682
Do(p, Version);
683
Do(p, AuBufAvailable);
684
Do(p, sourcebuff);
685
Do(p, nextOutputHalf);
686
}
687
688
if (p.mode == p.MODE_READ) {
689
decoder = CreateAudioDecoder((PSPAudioType)audioType);
690
}
691
}
692
693