summaryrefslogtreecommitdiffstats
path: root/src/sound/MP3AudioFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sound/MP3AudioFile.cpp')
-rw-r--r--src/sound/MP3AudioFile.cpp329
1 files changed, 329 insertions, 0 deletions
diff --git a/src/sound/MP3AudioFile.cpp b/src/sound/MP3AudioFile.cpp
new file mode 100644
index 0000000..700169f
--- /dev/null
+++ b/src/sound/MP3AudioFile.cpp
@@ -0,0 +1,329 @@
+// -*- c-basic-offset: 4 -*-
+
+/*
+ Rosegarden
+ A sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral right of the authors to claim authorship of this work
+ has been asserted.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "MP3AudioFile.h"
+
+#ifdef HAVE_LIBMAD
+
+#include <mad.h>
+
+namespace Rosegarden
+{
+
+
+/*
+ * This is a private message structure. A generic pointer to this structure
+ * is passed to each of the callback functions. Put here any data you need
+ * to access from within the callbacks.
+ */
+
+struct player
+{
+ unsigned char const *start;
+ unsigned long length;
+ //int default_driver;
+ //ao_device *device;
+ //ao_sample_format format;
+ //class SoundTouch *touch;
+};
+
+
+
+MP3AudioFile::MP3AudioFile(const unsigned int &id,
+ const std::string &name,
+ const std::string &fileName):
+ AudioFile(id, name, fileName)
+{
+ m_type = MP3;
+}
+
+
+MP3AudioFile::MP3AudioFile(const std::string &fileName,
+ unsigned int /*channels*/,
+ unsigned int /*sampleRate*/,
+ unsigned int /*bytesPerSecond*/,
+ unsigned int /*bytesPerSample*/,
+ unsigned int /*bitsPerSample*/):
+ AudioFile(0, std::string(""), fileName)
+{
+ m_type = MP3;
+}
+
+
+MP3AudioFile::~MP3AudioFile()
+{}
+
+bool
+MP3AudioFile::open()
+{
+ // if already open
+ if (m_inFile && (*m_inFile))
+ return true;
+
+ m_inFile = new std::ifstream(m_fileName.c_str(),
+ std::ios::in | std::ios::binary);
+
+ if (!(*m_inFile)) {
+ m_type = UNKNOWN;
+ return false;
+ }
+
+ // Get the file size and store it for comparison later
+ m_fileSize = m_fileInfo->size();
+
+ try {
+ parseHeader();
+ } catch (BadSoundFileException s) {
+ throw(s);
+ }
+
+ return true;
+}
+
+bool
+MP3AudioFile::write()
+{
+ return false;
+}
+
+void
+MP3AudioFile::close()
+{}
+
+void
+MP3AudioFile::parseHeader()
+{
+ const std::string MP3_TAG("TAG");
+ if (m_inFile == 0)
+ return ;
+
+ // store size conveniently
+ m_fileSize = m_fileInfo->size();
+
+ if (m_fileSize == 0) {
+ std::string mess = std::string("\"") + m_fileName +
+ std::string("\" is empty - invalid MP3 file");
+ throw(mess);
+ }
+
+ // seek to beginning
+ m_inFile->seekg(0, std::ios::beg);
+
+ // get some header information
+ //
+ const int bufferLength = 3096;
+ std::string hS = getBytes(bufferLength);
+ bool foundMP3 = false;
+
+ for (unsigned int i = 0; i < hS.length() - 1; ++i) {
+ if ((hS[i] & 0xff) == 0xff && (hS[i + 1] & 0xe0) == 0xe0) {
+ foundMP3 = true;
+ break;
+ }
+ }
+
+ if (foundMP3 == false || (int)hS.length() < bufferLength) {
+ std::string mess = std::string("\"") + m_fileName +
+ std::string("\" doesn't appear to be a valid MP3 file");
+ throw(mess);
+ }
+
+ // guess most likely values - these are reset during decoding
+ m_channels = 2;
+ m_sampleRate = 44100;
+
+ mad_synth synth;
+ mad_frame frame;
+ mad_stream stream;
+
+ mad_synth_init(&synth);
+ mad_stream_init(&stream);
+ mad_frame_init(&frame);
+
+ /*
+ mad_stream_buffer(&stream, hS.data(), hS.length());
+
+ if (mad_header_decode(&frame.header, &stream) == -1)
+ {
+ throw("Can't decode header");
+ }
+
+ mad_frame_decode(&frame, &stream);
+
+ m_sampleRate = frame.header.samplerate;
+
+ mad_synth_frame(&synth, &frame);
+ struct mad_pcm *pcm = &synth.pcm;
+
+ m_channels = pcm->channels;
+ */
+
+ /*
+ struct player player;
+ struct mad_decoder decoder;
+ struct stat stat;
+ void *fdm;
+ int result;
+
+ if (fstat(fd, &stat) == -1 ||
+ stat.st_size == 0)
+ return 0;
+
+ fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (fdm == MAP_FAILED) {
+ fprintf(stderr, "mmap failed, aborting...\n");
+ return 0;
+ }
+
+ player.start = (unsigned char *)fdm;
+ player.length = stat.st_size;
+ player.default_driver = ao_default_driver_id();
+ player.device = NULL;
+ player.touch = new SoundTouch;
+ player.touch->setTempo(tempo);
+ player.touch->setPitch(pitch);
+ mad_decoder_init(&decoder, &player,
+ input, 0 , 0 , process_output,
+ decode_error, 0);
+
+ result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
+ mad_decoder_finish(&decoder);
+ delete player.touch;
+ ao_close(player.device);
+ if (munmap((void *)player.start, stat.st_size) == -1)
+ return 4;
+
+ return result;
+ */
+}
+
+std::streampos
+MP3AudioFile::getDataOffset()
+{
+ return 0;
+}
+
+bool
+MP3AudioFile::scanTo(const RealTime & /*time*/)
+{
+ return false;
+}
+
+bool
+MP3AudioFile::scanTo(std::ifstream * /*file*/, const RealTime & /*time*/)
+{
+ return false;
+}
+
+
+// Scan forward in a file by a certain amount of time
+//
+bool
+MP3AudioFile::scanForward(const RealTime & /*time*/)
+{
+ return false;
+}
+
+bool
+MP3AudioFile::scanForward(std::ifstream * /*file*/, const RealTime & /*time*/)
+{
+ return false;
+}
+
+
+// Return a number of samples - caller will have to
+// de-interleave n-channel samples themselves.
+//
+std::string
+MP3AudioFile::getSampleFrames(std::ifstream * /*file*/,
+ unsigned int /*frames*/)
+{
+ return "";
+}
+
+unsigned int
+MP3AudioFile::getSampleFrames(std::ifstream * /*file*/,
+ char * /* buf */,
+ unsigned int /*frames*/)
+{
+ return 0;
+}
+
+std::string
+MP3AudioFile::getSampleFrames(unsigned int /*frames*/)
+{
+ return "";
+}
+
+
+// Return a number of (possibly) interleaved samples
+// over a time slice from current file pointer position.
+//
+std::string
+MP3AudioFile::getSampleFrameSlice(std::ifstream * /*file*/,
+ const RealTime & /*time*/)
+{
+ return "";
+}
+
+std::string
+MP3AudioFile::getSampleFrameSlice(const RealTime & /*time*/)
+{
+ return "";
+}
+
+
+// Append a string of samples to an already open (for writing)
+// audio file.
+//
+bool
+MP3AudioFile::appendSamples(const std::string & /*buffer*/)
+{
+ return false;
+}
+
+bool
+MP3AudioFile::appendSamples(const char * /*buffer*/, unsigned int)
+{
+ return false;
+}
+
+
+// Get the length of the sample in Seconds/Microseconds
+//
+RealTime
+MP3AudioFile::getLength()
+{
+ return RealTime(0, 0);
+}
+
+void
+MP3AudioFile::printStats()
+{}
+
+
+
+
+
+}
+
+#endif // HAVE_LIBMAD