7731179abd6b — Chris Cannam 27 days ago
First attempt at MiniMP3 wrapper
M Makefile +3 -2
@@ 9,6 9,7 @@ 
 #  -DHAVE_OGGZ -DHAVE_FISHSOUND
 #                      * Read Ogg/Vorbis files using oggz
 #  -DHAVE_OPUS         * Read Opus files using libopus
+#  -DHAVE_MINIMP3      * Read mp3 files using minimp3
 #  -DHAVE_MEDIAFOUNDATION
 #                      * Read various formats using MediaFoundation on Windows
 #  -DHAVE_COREAUDIO    * Read various formats using CoreAudio on macOS/iOS

          
@@ 17,12 18,12 @@ 
 # will also be provided, as none of the other libraries have write
 # support included here.
 
-AUDIOSTREAM_DEFINES := -DHAVE_LIBSNDFILE -DHAVE_OGGZ -DHAVE_FISHSOUND -DHAVE_OPUS
+AUDIOSTREAM_DEFINES := -DHAVE_LIBSNDFILE -DHAVE_OGGZ -DHAVE_FISHSOUND -DHAVE_OPUS -DHAVE_MINIMP3
 
 
 # Add any related includes and libraries here
 #
-THIRD_PARTY_INCLUDES	:= -I/usr/include/opus
+THIRD_PARTY_INCLUDES	:= -I/usr/include/opus -I../thirdparty/minimp3
 THIRD_PARTY_LIBS	:=
 
 

          
M build/Makefile.inc +4 -0
@@ 31,6 31,8 @@ src/AudioReadStreamFactory.o: src/WavFil
 src/AudioReadStreamFactory.o: src/OggVorbisReadStream.cpp
 src/AudioReadStreamFactory.o: src/MediaFoundationReadStream.cpp
 src/AudioReadStreamFactory.o: src/CoreAudioReadStream.cpp
+src/AudioReadStreamFactory.o: src/OpusReadStream.cpp
+src/AudioReadStreamFactory.o: src/MiniMP3ReadStream.cpp
 src/AudioWriteStreamFactory.o: ./bqaudiostream/AudioWriteStreamFactory.h
 src/AudioWriteStreamFactory.o: ./bqaudiostream/AudioWriteStream.h
 src/AudioWriteStreamFactory.o: ./bqaudiostream/Exceptions.h

          
@@ 48,3 50,5 @@ src/WavFileReadStream.o: ./bqaudiostream
 src/CoreAudioWriteStream.o: ./bqaudiostream/AudioWriteStream.h
 src/CoreAudioReadStream.o: ./bqaudiostream/AudioReadStream.h
 src/OggVorbisReadStream.o: ./bqaudiostream/AudioReadStream.h
+src/OpusReadStream.o: ./bqaudiostream/AudioReadStream.h
+src/MiniMP3ReadStream.o: ./bqaudiostream/AudioReadStream.h

          
M src/AudioReadStreamFactory.cpp +1 -0
@@ 125,6 125,7 @@ AudioReadStreamFactory::getFileFilter()
 
 #include "WavFileReadStream.cpp"
 #include "OggVorbisReadStream.cpp"
+#include "MiniMP3ReadStream.cpp"
 #include "MediaFoundationReadStream.cpp"
 #include "CoreAudioReadStream.cpp"
 #include "OpusReadStream.cpp"

          
A => src/MiniMP3ReadStream.cpp +133 -0
@@ 0,0 1,133 @@ 
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+/*
+    bqaudiostream
+
+    A small library wrapping various audio file read/write
+    implementations in C++.
+
+    Copyright 2007-2020 Particular Programs Ltd.
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of Chris Cannam and
+    Particular Programs Ltd shall not be used in advertising or
+    otherwise to promote the sale, use or other dealings in this
+    Software without prior written authorization.
+*/
+
+#ifdef HAVE_MINIMP3
+
+#define MINIMP3_IMPLEMENTATION
+#define MINIMP3_FLOAT_OUTPUT
+#include <minimp3_ex.h>
+
+#include "MiniMP3ReadStream.h"
+
+#include <sstream>
+
+namespace breakfastquay
+{
+
+static vector<string>
+getMiniMP3Extensions()
+{
+    vector<string> extensions;
+    extensions.push_back("mp3");
+    return extensions;
+}
+
+static
+AudioReadStreamBuilder<MiniMP3ReadStream>
+minimp3builder(
+    string("http://breakfastquay.com/rdf/turbot/audiostream/MiniMP3ReadStream"),
+    getMiniMP3Extensions()
+    );
+
+class MiniMP3ReadStream::D
+{
+public:
+    D() { }
+    mp3dec_ex_t dec;
+};
+
+MiniMP3ReadStream::MiniMP3ReadStream(string path) :
+    m_path(path),
+    m_d(new D)
+{
+    //!!! Windows: use wchar versions
+    
+    m_channelCount = 0;
+    m_sampleRate = 0;
+
+    int err = mp3dec_ex_open(&m_d->dec, path.c_str(), MP3D_DO_NOT_SCAN);
+    if (err) {
+        ostringstream os;
+        os << "MiniMP3ReadStream: Unable to open file (error code " << err << ")";
+        m_error = os.str();
+        if (err == MP3D_E_IOERROR) {
+            throw FileNotFound(m_path);
+        } else {
+            throw InvalidFileFormat(m_path, "failed to open audio file");
+        }
+    }
+
+    m_channelCount = m_d->dec.info.channels;
+    m_sampleRate = m_d->dec.info.hz;
+}
+
+size_t
+MiniMP3ReadStream::getFrames(size_t count, float *frames)
+{
+    if (m_error != "") return 0;
+    if (count == 0) return 0;
+
+//    cerr << "getFrames: working" << endl;
+
+    size_t desired = count * m_channelCount;
+    size_t obtained = mp3dec_ex_read(&m_d->dec, frames, desired);
+
+    //!!! have to provide our own tags support?
+    
+    if (obtained < desired) {
+        if (m_d->dec.last_error) {
+            ostringstream os;
+            os << "MiniMP3ReadStream: Failed to read from file (error code "
+               << m_d->dec.last_error << ")";
+            m_error = os.str();
+            mp3dec_ex_close(&m_d->dec);
+            throw InvalidFileFormat(m_path, "error in decoder");
+        }
+    }
+
+    return obtained / m_channelCount;
+}
+
+MiniMP3ReadStream::~MiniMP3ReadStream()
+{
+    if (m_error != "") {
+        mp3dec_ex_close(&m_d->dec);
+    }
+    delete m_d;
+}
+
+}
+
+#endif
+

          
A => src/MiniMP3ReadStream.h +72 -0
@@ 0,0 1,72 @@ 
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+/*
+    bqaudiostream
+
+    A small library wrapping various audio file read/write
+    implementations in C++.
+
+    Copyright 2007-2020 Particular Programs Ltd.
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use, copy,
+    modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the names of Chris Cannam and
+    Particular Programs Ltd shall not be used in advertising or
+    otherwise to promote the sale, use or other dealings in this
+    Software without prior written authorization.
+*/
+
+#ifndef BQ_MINIMP3_READ_STREAM_H
+#define BQ_MINIMP3_READ_STREAM_H
+
+#include "AudioReadStream.h"
+
+#ifdef HAVE_MINIMP3
+
+namespace breakfastquay
+{
+    
+class MiniMP3ReadStream : public AudioReadStream
+{
+public:
+    MiniMP3ReadStream(std::string path);
+    virtual ~MiniMP3ReadStream();
+
+    virtual std::string getTrackName() const { return m_track; }
+    virtual std::string getArtistName() const { return m_artist; }
+
+    virtual std::string getError() const { return m_error; }
+
+protected:
+    virtual size_t getFrames(size_t count, float *frames);
+
+    std::string m_path;
+    std::string m_error;
+    std::string m_track;
+    std::string m_artist;
+
+    class D;
+    D *m_d;
+};
+
+}
+
+#endif
+
+#endif

          
M test/test.pro +1 -1
@@ 10,7 10,7 @@ QT -= gui
 DESTDIR = .
 QMAKE_LIBDIR += . ..
 
-LIBS += -L.. -lbqaudiostream -L../../bqresample -lbqresample -L../../bqvec -lbqvec -lsndfile -loggz -lfishsound -lopusfile -lopus -logg
+LIBS += -L.. -lbqaudiostream -L../../bqresample -lbqresample -L../../bqvec -lbqvec -lsndfile -loggz -lfishsound -lopusfile -lopus -logg -lsamplerate
 
 INCLUDEPATH += . .. ../../bqvec ../../bqresample ../../bqthingfactory
 DEPENDPATH += . .. ../../bqvec ../../bqresample ../../bqthingfactory