blob: a11a496f1cc066175389a88f8bc704c95c66b2c8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
#ifndef MIXXX_SOUNDSOURCEMP3_H
#define MIXXX_SOUNDSOURCEMP3_H
#include "sources/soundsourceprovider.h"
#ifdef _MSC_VER
// So mad.h doesn't try to use inline assembly which MSVC doesn't support.
// Notably, FPM_64BIT does not require a 64-bit machine. It merely requires a
// compiler that supports 64-bit types.
#define FPM_64BIT
#endif
#include <mad.h>
#include <QFile>
#include <vector>
namespace mixxx {
class SoundSourceMp3 final : public SoundSource {
public:
explicit SoundSourceMp3(const QUrl& url);
~SoundSourceMp3() override;
void close() override;
protected:
ReadableSampleFrames readSampleFramesClamped(
WritableSampleFrames sampleFrames) override;
private:
OpenResult tryOpen(
OpenMode mode,
const OpenParams& params) override;
QFile m_file;
quint64 m_fileSize;
unsigned char* m_pFileData;
/** Struct used to store mad frames for seeking */
struct SeekFrameType {
SINT frameIndex;
const unsigned char* pInputData;
};
/** It is not possible to make a precise seek in an mp3 file without decoding the whole stream.
* To have precise seek within a limited range from the current decode position, we keep track
* of past decoded frame, and their exact position. If a seek occurs and it is within the
* range of frames we keep track of a precise seek occurs, otherwise an imprecise seek is performed
*/
typedef std::vector<SeekFrameType> SeekFrameList;
SeekFrameList m_seekFrameList; // ordered-by frameIndex
SINT m_avgSeekFrameCount; // avg. sample frames per MP3 frame
void addSeekFrame(SINT frameIndex, const unsigned char* pInputData);
/** Returns the position in m_seekFrameList of the requested frame index. */
SINT findSeekFrameIndex(SINT frameIndex) const;
SINT m_curFrameIndex;
// NOTE(uklotzde): Each invocation of initDecoding() must be
// followed by an invocation of finishDecoding().
void initDecoding();
void restartDecoding(const SeekFrameType& seekFrame);
void finishDecoding();
// MAD decoder
mad_stream m_madStream;
mad_frame m_madFrame;
mad_synth m_madSynth;
SINT m_madSynthCount; // left overs from the previous read
std::vector<unsigned char> m_leftoverBuffer;
};
class SoundSourceProviderMp3: public SoundSourceProvider {
public:
QString getName() const override;
QStringList getSupportedFileExtensions() const override;
SoundSourcePointer newSoundSource(const QUrl& url) override {
return newSoundSourceFromUrl<SoundSourceMp3>(url);
}
};
} // namespace mixxx
#endif // MIXXX_SOUNDSOURCEMP3_H
|