diff options
Diffstat (limited to 'src/sound/MP3AudioFile.cpp')
-rw-r--r-- | src/sound/MP3AudioFile.cpp | 329 |
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 |