23 #include "../../errors.hpp" 24 #include "../../messages.h" 25 #include "../audio_source.hpp" 26 #include "../sample_formats.hpp" 31 const size_t Mp3AudioSource::BUFFER_SIZE = 16384;
33 Mp3AudioSource::Mp3AudioSource(
const std::string &path)
34 :
AudioSource(path), buffer(BUFFER_SIZE), context(nullptr)
36 this->context = mpg123_new(
nullptr,
nullptr);
37 mpg123_format_none(this->context);
39 const long *rates =
nullptr;
41 mpg123_rates(&rates, &nrates);
42 for (
size_t r = 0; r < nrates; r++) {
43 Debug() <<
"trying to enable formats at " << rates[r]
48 if (mpg123_open(this->context, path.c_str()) == MPG123_ERR) {
49 throw FileError(
"mp3: can't open " + path +
": " +
50 mpg123_strerror(this->context));
54 Mp3AudioSource::~Mp3AudioSource()
56 mpg123_delete(this->context);
57 this->context =
nullptr;
60 void Mp3AudioSource::AddFormat(
long rate)
64 if (mpg123_format(this->context, rate, MPG123_STEREO | MPG123_MONO,
65 (MPG123_ENC_UNSIGNED_8 | MPG123_ENC_SIGNED_8 |
66 MPG123_ENC_SIGNED_16 | MPG123_ENC_SIGNED_32 |
67 MPG123_ENC_FLOAT_32)) == MPG123_ERR) {
71 Debug() <<
"can't support" << rate << std::endl;
75 std::uint8_t Mp3AudioSource::ChannelCount()
const 77 assert(this->context !=
nullptr);
80 mpg123_getformat(this->context,
nullptr, &chans,
nullptr);
82 return static_cast<std::uint8_t
>(chans);
85 std::uint32_t Mp3AudioSource::SampleRate()
const 87 assert(this->context !=
nullptr);
90 mpg123_getformat(this->context, &rate,
nullptr,
nullptr);
96 assert(rate <= INT32_MAX);
97 return static_cast<std::uint32_t
>(rate);
100 std::uint64_t Mp3AudioSource::Seek(std::uint64_t in_samples)
102 assert(this->context !=
nullptr);
105 auto clen =
static_cast<unsigned long>(mpg123_length(this->context));
106 if (clen < in_samples) {
107 Debug() <<
"mp3: seek at" << in_samples <<
"past EOF at" << clen
112 if (mpg123_seek(this->context, in_samples, SEEK_SET) == MPG123_ERR) {
113 Debug() <<
"mp3: seek failed:" << mpg123_strerror(this->context)
121 return mpg123_tell(this->context);
124 Mp3AudioSource::DecodeResult Mp3AudioSource::Decode()
126 assert(this->context !=
nullptr);
128 auto buf =
reinterpret_cast<unsigned char *
>(&this->buffer.front());
130 int err = mpg123_read(this->context, buf, this->buffer.size(), &rbytes);
132 DecodeVector decoded;
133 DecodeState decode_state;
135 if (err == MPG123_DONE) {
136 decode_state = DecodeState::END_OF_FILE;
137 }
else if (err != MPG123_OK && err != MPG123_NEW_FORMAT) {
138 Debug() <<
"mp3: decode error:" << mpg123_strerror(this->context)
140 decode_state = DecodeState::END_OF_FILE;
142 decode_state = DecodeState::DECODING;
145 auto front = this->buffer.begin();
146 decoded = DecodeVector(front, front + rbytes);
149 return std::make_pair(decode_state, decoded);
154 assert(this->context !=
nullptr);
157 mpg123_getformat(this->context,
nullptr,
nullptr, &encoding);
160 case MPG123_ENC_UNSIGNED_8:
162 case MPG123_ENC_SIGNED_8:
164 case MPG123_ENC_SIGNED_16:
166 case MPG123_ENC_SIGNED_32:
168 case MPG123_ENC_FLOAT_32:
174 "unsupported sample rate, should not " An object responsible for decoding an audio file.
Declaration of the Mp3AudioSource class.
An Error signifying that playd can't read a file.
const std::string MSG_SEEK_FAIL
Message shown when an attempt to seek fails.
An Error signifying that playd can't seek in a file.
Class for telling the human what playd is doing.
An Error signifying that playd has hit an internal snag.