aboutsummaryrefslogtreecommitdiff
path: root/Src/mp3-mpg123/nsvmain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/mp3-mpg123/nsvmain.cpp')
-rw-r--r--Src/mp3-mpg123/nsvmain.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/Src/mp3-mpg123/nsvmain.cpp b/Src/mp3-mpg123/nsvmain.cpp
new file mode 100644
index 00000000..539fc75e
--- /dev/null
+++ b/Src/mp3-mpg123/nsvmain.cpp
@@ -0,0 +1,93 @@
+#include "../nsv/nsvlib.h"
+#include "../nsv/dec_if.h"
+#include "nsvmain.h"
+#include "../nsutil/pcm.h"
+
+MP3_Decoder::MP3_Decoder()
+{
+ decoder = mpg123_new(NULL, NULL);
+ long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
+ mpg123_param(decoder, MPG123_FLAGS, flags, 0);
+ mpg123_param(decoder, MPG123_RVA, MPG123_RVA_OFF, 0);
+ memset(pcm_buf, 0, sizeof(pcm_buf));
+ mpg123_open_feed(decoder);
+ fused = 0; pcm_buf_used = 0; pcm_offs = 0;
+}
+
+int MP3_Decoder::decode(void *in, int in_len,
+ void *out, int *out_len,
+ unsigned int out_fmt[8])
+{
+ int rval = 1;
+ if (fused < in_len)
+ {
+ int l = 4096;
+ if (l > in_len - fused) l = in_len - fused;
+ if (l) mpg123_feed(decoder, (unsigned char *)in + fused, l);
+ fused += l;
+ }
+
+ if (!pcm_buf_used)
+ {
+ mpg123_read(decoder, (unsigned char *)pcm_buf, sizeof(pcm_buf), &pcm_buf_used);
+
+ pcm_offs = 0;
+ }
+
+ if (pcm_buf_used)
+ {
+ size_t numSamples = *out_len / 2;
+ if (numSamples > (pcm_buf_used/sizeof(float)))
+ numSamples = pcm_buf_used/sizeof(float);
+ nsutil_pcm_FloatToInt_Interleaved(out, pcm_buf+pcm_offs, 16, numSamples);
+ pcm_buf_used -= numSamples*sizeof(float);
+ pcm_offs += (int)numSamples;
+ *out_len = 2*(int)numSamples;
+ }
+ else
+ {
+ if (fused >= in_len) { fused = 0; rval = 0; }
+ *out_len = 0;
+ }
+ mpg123_frameinfo frameInfo;
+ if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
+ int nch = (frameInfo.mode == MPG123_M_MONO)?1:2;
+ int srate = frameInfo.rate;
+ out_fmt[0] = (nch && srate) ? NSV_MAKETYPE('P', 'C', 'M', ' ') : 0;
+ out_fmt[1] = srate;
+ out_fmt[2] = nch;
+ out_fmt[3] = (nch && srate) ? 16 : 0;
+ out_fmt[4] = frameInfo.bitrate;
+ }
+ return rval;
+}
+
+void MP3_Decoder::flush()
+{
+ fused = 0;
+ pcm_buf_used = 0;
+ pcm_offs = 0;
+ mpg123_open_feed(decoder);
+}
+
+extern "C"
+{
+ __declspec(dllexport) IAudioDecoder *CreateAudioDecoder(unsigned int fmt, IAudioOutput **output)
+ {
+ switch (fmt)
+ {
+ case NSV_MAKETYPE('M', 'P', '3', ' '):
+ return new MP3_Decoder;
+
+ default:
+ return NULL;
+ }
+ }
+
+ __declspec(dllexport) void DeleteAudioDecoder(IAudioDecoder *decoder)
+ {
+ if (decoder)
+ delete decoder;
+
+ }
+}