traverso-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Traverso-commit] traverso/src/core MonoReader.cpp MonoReader.h R...


From: Ben Levitt
Subject: [Traverso-commit] traverso/src/core MonoReader.cpp MonoReader.h R...
Date: Fri, 06 Jul 2007 22:13:33 +0000

CVSROOT:        /sources/traverso
Module name:    traverso
Changes by:     Ben Levitt <benjie>     07/07/06 22:13:33

Modified files:
        src/core       : MonoReader.cpp MonoReader.h ReadSource.cpp 
                         core.pro 
Added files:
        src/core       : AbstractAudioReader.cpp AbstractAudioReader.h 
                         ResampleAudioReader.cpp ResampleAudioReader.h 
                         SFAudioReader.cpp SFAudioReader.h 
                         VorbisAudioReader.cpp VorbisAudioReader.h 

Log message:
        Abstract out the audio reading code, add dynamic resampling which, 
unfortunately, doesn't yet work right

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/MonoReader.cpp?cvsroot=traverso&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/MonoReader.h?cvsroot=traverso&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/ReadSource.cpp?cvsroot=traverso&r1=1.37&r2=1.38
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/core.pro?cvsroot=traverso&r1=1.29&r2=1.30
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/AbstractAudioReader.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/AbstractAudioReader.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/ResampleAudioReader.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/ResampleAudioReader.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/SFAudioReader.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/SFAudioReader.h?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/VorbisAudioReader.cpp?cvsroot=traverso&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/traverso/src/core/VorbisAudioReader.h?cvsroot=traverso&rev=1.1

Patches:
Index: MonoReader.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/core/MonoReader.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- MonoReader.cpp      22 Jun 2007 12:29:28 -0000      1.17
+++ MonoReader.cpp      6 Jul 2007 22:13:32 -0000       1.18
@@ -32,6 +32,7 @@
 #include <AudioDevice.h>
 #include <DiskIO.h>
 #include <Song.h>
+#include "AbstractAudioReader.h"
 
 // Always put me below _all_ includes, this is needed
 // in case we run with memory leak detection enabled!
@@ -44,7 +45,7 @@
          m_source(source),
          m_buffer(0),
          m_peak(0),
-         m_sf(0),
+         m_audioReader(0),
          m_sourceChannelCount(sourceChannelCount), 
          m_channelNumber(channelNumber), 
          m_fileName(fileName)
@@ -62,10 +63,8 @@
        if (m_peak) {
                m_peak->close();
        }
-       if (m_sf) {
-               if (sf_close (m_sf)) {
-                       qWarning("sf_close returned an error!");
-               }
+       if (m_audioReader) {
+               delete m_audioReader;
        }
        
        delete m_bufferstatus;
@@ -76,7 +75,7 @@
 {
        PENTER;
        
-       Q_ASSERT(m_sf == 0);
+       Q_ASSERT(m_audioReader == 0);
        
        m_rbFileReadPos = 0;
        m_rbRelativeFileReadPos = 0;
@@ -87,37 +86,35 @@
        m_bufferUnderRunDetected = m_wasActivated = 0;
        m_isCompressedFile = false;
 
-       /* although libsndfile says we don't need to set this,
-       valgrind and source code shows us that we do.
-       Really? Look it up !
-       */
-       memset (&m_sfinfo, 0, sizeof(m_sfinfo));
 
+       //
+       // Uncomment the next line, and comment the one after that to try out 
dynamic resampling
+       //
 
-       if ((m_sf = sf_open ((m_fileName.toUtf8().data()), SFM_READ, 
&m_sfinfo)) == 0) {
-               PERROR("Couldn't open soundfile (%s)", QS_C(m_fileName));
+       //if ((m_audioReader = 
AbstractAudioReader::create_resampled_audio_reader(m_fileName)) == 0) {
+       if ((m_audioReader = 
AbstractAudioReader::create_audio_reader(m_fileName)) == 0) {
                return ReadSource::COULD_NOT_OPEN_FILE;
        }
 
-       if (m_sourceChannelCount > m_sfinfo.channels) {
-               PERROR("ReadAudioSource: file only contains %d channels; %d is 
invalid as a channel number", m_sfinfo.channels, m_sourceChannelCount);
-               sf_close (m_sf);
-               m_sf = 0;
+       if (m_sourceChannelCount > m_audioReader->get_num_channels()) {
+               PERROR("ReadAudioSource: file only contains %d channels; %d is 
invalid as a channel number", m_audioReader->get_num_channels(), 
m_sourceChannelCount);
+               delete m_audioReader;
+               m_audioReader = 0;
                return ReadSource::INVALID_CHANNEL_COUNT;
        }
 
-       if (m_sfinfo.channels == 0) {
-               PERROR("ReadAudioSource: not a valid channel count: %d", 
m_sfinfo.channels);
-               sf_close (m_sf);
-               m_sf = 0;
+       if (m_audioReader->get_num_channels() == 0) {
+               PERROR("ReadAudioSource: not a valid channel count: %d", 
m_audioReader->get_num_channels());
+               delete m_audioReader;
+               m_audioReader = 0;
                return ReadSource::ZERO_CHANNELS;
        }
 
-       m_source->m_length = m_sfinfo.frames;
-       m_length = m_sfinfo.frames;
-       m_source->m_rate = m_sfinfo.samplerate;
+       m_source->m_length = m_audioReader->get_length();
+       m_length = m_audioReader->get_length();
+       m_source->m_rate = m_audioReader->get_rate();
 
-       if ( (m_sfinfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC ) {
+       if ( m_audioReader->is_compressed() ) {
                m_isCompressedFile = true;
        }
        
@@ -129,28 +126,11 @@
 
 int MonoReader::file_read (audio_sample_t* dst, nframes_t start, nframes_t 
cnt, audio_sample_t* readbuffer) const
 {
-//     PWARN("file_read");
-       // this equals checking if init() is called!
-       Q_ASSERT(m_sf);
-       
-       if (start >= m_source->m_length) {
-               return 0;
-       }
-       
-//#define profile
-       
-       if (sf_seek (m_sf, (off_t) start, SEEK_SET) < 0) {
-               char errbuf[256];
-               sf_error_str (0, errbuf, sizeof (errbuf) - 1);
-               PERROR("ReadAudioSource: could not seek to frame %d within %s 
(%s)", start, QS_C(m_fileName), errbuf);
-               return 0;
-       }
-
 #if defined (profile)
        trav_time_t starttime = get_microseconds();
 #endif
-       if (m_sfinfo.channels == 1) {
-               int result = sf_read_float (m_sf, dst, cnt);
+       if (m_audioReader->get_num_channels() == 1) {
+               int result = m_audioReader->read_from(dst, start, cnt);
 #if defined (profile)
                int processtime = (int) (get_microseconds() - starttime);
                if (processtime > 40000)
@@ -160,25 +140,25 @@
        }
 
        float *ptr;
-       uint real_cnt = cnt * m_sfinfo.channels;
+       uint real_cnt = cnt * m_audioReader->get_num_channels();
        
        // The readbuffer 'assumes' that there is max 2 channels...
-       Q_ASSERT(m_sfinfo.channels <= 2);
+       Q_ASSERT(m_audioReader->get_num_channels() <= 2);
        
-       int nread = sf_read_float (m_sf, readbuffer, real_cnt);
+       int nread = m_audioReader->read_from(readbuffer, start, real_cnt);
 #if defined (profile)
        int processtime = (int) (get_microseconds() - starttime);
        if (processtime > 40000)
                printf("Process time for %s, channel %d: %d useconds\n\n", 
QS_C(m_fileName), m_channelNumber, processtime);
 #endif
        ptr = readbuffer + m_channelNumber;
-       nread /= m_sfinfo.channels;
+       nread /= m_audioReader->get_num_channels();
 
        /* stride through the interleaved data */
 
        for (int32_t n = 0; n < nread; ++n) {
                dst[n] = *ptr;
-               ptr += m_sfinfo.channels;
+               ptr += m_audioReader->get_num_channels();
        }
 
 
@@ -417,11 +397,7 @@
        m_bufferstatus->bufferUnderRun = m_bufferUnderRunDetected;
        m_bufferstatus->needSync = m_needSync;
 
-       if ( ! m_isCompressedFile) {
                m_bufferstatus->priority = (int) (freespace / m_chunkSize);
-       } else {
-               m_bufferstatus->priority = (int) (freespace / m_chunkSize);
-       }
        
        return m_bufferstatus;
 }

Index: MonoReader.h
===================================================================
RCS file: /sources/traverso/traverso/src/core/MonoReader.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- MonoReader.h        4 Jun 2007 18:37:16 -0000       1.4
+++ MonoReader.h        6 Jul 2007 22:13:32 -0000       1.5
@@ -25,10 +25,10 @@
 #include "AudioSource.h"
 #include "RingBufferNPT.h"
 #include "defines.h"
-#include "sndfile.h"
 
 
 class AudioClip;
+class AbstractAudioReader;
 class Peak;
 class ReadSource;
 class QString;
@@ -63,8 +63,7 @@
        ReadSource*     m_source;
        RingBufferNPT<float>*   m_buffer;
        Peak*           m_peak;
-       SNDFILE*        m_sf;
-       SF_INFO         m_sfinfo;
+       AbstractAudioReader*    m_audioReader;
        int             m_sourceChannelCount;
        int             m_channelNumber;
        uint            m_length;

Index: ReadSource.cpp
===================================================================
RCS file: /sources/traverso/traverso/src/core/ReadSource.cpp,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -b -r1.37 -r1.38
--- ReadSource.cpp      26 Jun 2007 18:07:56 -0000      1.37
+++ ReadSource.cpp      6 Jul 2007 22:13:32 -0000       1.38
@@ -21,6 +21,7 @@
 
 #include "ReadSource.h"
 #include "MonoReader.h"
+#include "AbstractAudioReader.h"
 
 #include "Peak.h"
 #include "ProjectManager.h"
@@ -68,13 +69,13 @@
        , m_error(0)
        , m_clip(0)
 {
-       SNDFILE* sf;
-       SF_INFO  sfinfo;
+       AbstractAudioReader* reader = 
AbstractAudioReader::create_audio_reader(m_fileName);
+
        m_channelCount = 0;
        
-       if ((sf = sf_open (QS_C(m_fileName), SFM_READ, &sfinfo)) != 0) {
-               m_channelCount = sfinfo.channels;
-               sf_close(sf);
+       if (reader) {
+               m_channelCount = reader->get_num_channels();
+               delete reader;
        }
 
        m_fileCount = 1;

Index: core.pro
===================================================================
RCS file: /sources/traverso/traverso/src/core/core.pro,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -b -r1.29 -r1.30
--- core.pro    21 Jun 2007 14:31:10 -0000      1.29
+++ core.pro    6 Jul 2007 22:13:33 -0000       1.30
@@ -50,7 +50,11 @@
        Snappable.cpp \
        TimeLine.cpp \
        Marker.cpp \
-       Themer.cpp
+       Themer.cpp \
+       AbstractAudioReader.cpp \
+       SFAudioReader.cpp \
+       ResampleAudioReader.cpp \
+       VorbisAudioReader.cpp
 HEADERS = precompile.h \
        AudioClip.h \
        AudioClipList.h \
@@ -94,7 +98,11 @@
        CommandPlugin.h \
        TimeLine.h \
        Marker.h \
-       Themer.h
+       Themer.h \
+       AbstractAudioReader.h \
+       SFAudioReader.h \
+       ResampleAudioReader.h \
+       VorbisAudioReader.h
 macx{
     QMAKE_LIBDIR += /usr/local/qt/lib
 }

Index: AbstractAudioReader.cpp
===================================================================
RCS file: AbstractAudioReader.cpp
diff -N AbstractAudioReader.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ AbstractAudioReader.cpp     6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,101 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#include "AbstractAudioReader.h"
+#include "SFAudioReader.h"
+#include "VorbisAudioReader.h"
+#include "ResampleAudioReader.h"
+
+#include <QString>
+
+// Always put me below _all_ includes, this is needed
+// in case we run with memory leak detection enabled!
+#include "Debugger.h"
+
+
+AbstractAudioReader::AbstractAudioReader(QString filename)
+ : QObject(0)
+{
+       m_fileName = filename;
+       m_nextFrame = 0;
+}
+
+
+AbstractAudioReader::~AbstractAudioReader()
+{
+}
+
+
+// Read cnt frames starting at start from the AudioReader, into dst
+// uses seek() and read() from AudioReader subclass
+int AbstractAudioReader::read_from(audio_sample_t* dst, nframes_t start, 
nframes_t cnt)
+{
+       if (m_nextFrame != start) {
+               if (!seek(start)) {
+                       return 0;
+               }
+       }
+       
+       int samplesRead = read(dst, cnt);
+       
+       return samplesRead;
+}
+
+
+// Static method used by other classes to get an AudioReader for the correct 
file type
+AbstractAudioReader* AbstractAudioReader::create_audio_reader(QString filename)
+{
+       AbstractAudioReader* newReader;
+       
+       if (VorbisAudioReader::can_decode(filename)) {
+               newReader = new VorbisAudioReader(filename);
+       }
+       else if (SFAudioReader::can_decode(filename)) {
+               newReader = new SFAudioReader(filename);
+       }
+       else {
+               return 0;
+       }
+       
+       if (newReader->get_rate() <= 0) {
+               PERROR("new reader has rate=0!");
+               return 0;
+       }
+
+       return newReader;
+}
+
+
+// Static method used by other classes to get an automatically resampling 
AudioReader that wraps
+// an AudioReader chosen by create_audio_reader().
+AbstractAudioReader* 
AbstractAudioReader::create_resampled_audio_reader(QString filename)
+{
+       ResampleAudioReader* newReader;
+
+       newReader = new ResampleAudioReader(filename);
+
+       if (newReader->get_rate() > 0) {
+               return newReader;
+       }
+       
+       return 0;
+}
+

Index: AbstractAudioReader.h
===================================================================
RCS file: AbstractAudioReader.h
diff -N AbstractAudioReader.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ AbstractAudioReader.h       6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,56 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#ifndef ABSTRACTAUDIOREADER_H
+#define ABSTRACTAUDIOREADER_H
+
+#include <QObject>
+
+#include "defines.h"
+
+class QString;
+
+class AbstractAudioReader : public QObject
+{
+Q_OBJECT
+public:
+       AbstractAudioReader(QString filename);
+       ~AbstractAudioReader();
+       
+       virtual int get_num_channels() = 0;
+       virtual int get_length() = 0;
+       virtual int get_rate() = 0;
+       virtual bool is_compressed() = 0;
+       int read_from(audio_sample_t* dst, nframes_t start, nframes_t cnt);
+       virtual bool seek(nframes_t start) = 0;
+       virtual int read(audio_sample_t* dst, nframes_t cnt) = 0;
+
+       static AbstractAudioReader* create_audio_reader(QString filename);
+       static AbstractAudioReader* create_resampled_audio_reader(QString 
filename);
+       static bool can_decode(QString filename) { return false; };
+
+protected:
+       QString         m_fileName;
+       nframes_t       m_nextFrame;
+
+};
+
+#endif

Index: ResampleAudioReader.cpp
===================================================================
RCS file: ResampleAudioReader.cpp
diff -N ResampleAudioReader.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ ResampleAudioReader.cpp     6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,186 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#include "ResampleAudioReader.h"
+#include <QString>
+#include "Utils.h"
+#include "AudioDevice.h"
+
+// Always put me below _all_ includes, this is needed
+// in case we run with memory leak detection enabled!
+#include "Debugger.h"
+
+
+// On init, creates a child AudioReader for any filetype, and a samplerate 
converter
+ResampleAudioReader::ResampleAudioReader(QString filename)
+ : AbstractAudioReader(filename)
+{
+       m_fileBuffer = 0;
+       m_fileBufferLength = 0;
+       
+       m_realReader = AbstractAudioReader::create_audio_reader(filename);
+       if (!m_realReader) {
+               PERROR("ResampleAudioReader: couldn't create AudioReader");
+               return;
+       }
+       
+       int error;
+       m_srcState = src_new (SRC_SINC_MEDIUM_QUALITY, 
m_realReader->get_num_channels(), &error);
+       if (!m_srcState) {
+               PERROR("ResampleAudioReader: couldn't create libSampleRate 
SRC_STATE");
+               delete m_realReader;
+               m_realReader = 0;
+       }
+       
+       m_srcData.end_of_input = 0;
+
+       seek(0);
+}
+
+
+ResampleAudioReader::~ResampleAudioReader()
+{
+       if (m_realReader) {
+               src_delete(m_srcState);
+               delete m_realReader;
+       }
+
+       if (m_fileBuffer) {
+               delete m_fileBuffer;
+       }
+}
+
+
+// Get from child AudioReader
+int ResampleAudioReader::get_num_channels()
+{
+       if (m_realReader) {
+               return m_realReader->get_num_channels();
+       }
+       return 0;
+}
+
+
+// Get from child AudioReader, convert from file's frames to song's frames
+int ResampleAudioReader::get_length()
+{
+       if (m_realReader) {
+               if (audiodevice().get_sample_rate() == 
m_realReader->get_rate()) {
+                       return m_realReader->get_length();
+               }
+               return file_to_song_frame(m_realReader->get_length());
+       }
+       return 0;
+}
+
+
+// Always the rate of the audio device
+int ResampleAudioReader::get_rate()
+{
+       return audiodevice().get_sample_rate();
+}
+
+
+// Still not sure if this is going to be necessary...
+bool ResampleAudioReader::is_compressed()
+{
+       if (m_realReader) {
+               return m_realReader->is_compressed();
+       }
+       return false;
+}
+
+
+// if no conversion is necessary, pass the seek straight to the child 
AudioReader,
+// otherwise convert and seek
+bool ResampleAudioReader::seek(nframes_t start)
+{
+       Q_ASSERT(m_realReader);
+       
+       if (audiodevice().get_sample_rate() == m_realReader->get_rate()) {
+               return m_realReader->seek(start);
+       }
+       
+       m_nextFrame = start;
+       
+       return m_realReader->seek(song_to_file_frame(start));
+}
+
+
+// 
+int ResampleAudioReader::read(audio_sample_t* dst, nframes_t cnt)
+{
+       Q_ASSERT(m_realReader);
+
+       if (audiodevice().get_sample_rate() == m_realReader->get_rate()) {
+               return m_realReader->read(dst, cnt);
+       }
+       
+       nframes_t fileCnt = song_to_file_frame(cnt) + 4;
+       
+       // make sure that the reusable m_fileBuffer is big enough for this read
+       if (m_fileBufferLength < fileCnt) {
+               if (m_fileBuffer) {
+                       delete m_fileBuffer;
+               }
+               m_fileBuffer = new audio_sample_t[fileCnt * get_num_channels()];
+               m_fileBufferLength = fileCnt;
+       }
+       
+       if (cnt) printf("nextFrame = %lu, fileCnt = %lu\n", m_nextFrame, 
fileCnt);
+       int samplesRead;
+       samplesRead = m_realReader->read_from(m_fileBuffer, m_nextFrame, 
fileCnt);
+       if (cnt) printf("samplesRead = %d\n", samplesRead);
+       // FIXME: Why does samplesRead==0 when it shouldn't???
+       
+       m_nextFrame += samplesRead / get_num_channels();
+       
+       m_srcData.data_in = m_fileBuffer;
+       m_srcData.input_frames = samplesRead / get_num_channels();
+       m_srcData.data_out = dst;
+       m_srcData.output_frames = cnt;
+       m_srcData.src_ratio = (double) audiodevice().get_sample_rate() / 
m_realReader->get_rate();
+       src_set_ratio(m_srcState, m_srcData.src_ratio);
+       
+       if (src_process(m_srcState, &m_srcData)) {
+               PERROR("src_process() error!");
+               return 0;
+       }
+       
+       return m_srcData.output_frames_gen * get_num_channels();
+}
+
+
+nframes_t ResampleAudioReader::song_to_file_frame(nframes_t frame)
+{
+       Q_ASSERT(m_realReader);
+       
+       return (nframes_t)(frame * (((double) m_realReader->get_rate()) / 
audiodevice().get_sample_rate()));
+}
+
+
+nframes_t ResampleAudioReader::file_to_song_frame(nframes_t frame)
+{
+       Q_ASSERT(m_realReader);
+       
+       return (nframes_t)(frame * (((double) audiodevice().get_sample_rate()) 
/ m_realReader->get_rate()));
+}
+

Index: ResampleAudioReader.h
===================================================================
RCS file: ResampleAudioReader.h
diff -N ResampleAudioReader.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ ResampleAudioReader.h       6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,56 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#ifndef RESAMPLEAUDIOREADER_H
+#define RESAMPLEAUDIOREADER_H
+
+#include <AbstractAudioReader.h>
+#include <samplerate.h>
+
+
+class ResampleAudioReader : public AbstractAudioReader
+{
+public:
+       ResampleAudioReader(QString filename);
+       ~ResampleAudioReader();
+
+       int get_num_channels();
+       int get_length();
+       int get_rate();
+       bool is_compressed();
+       bool seek(nframes_t start);
+       int read(audio_sample_t* dst, nframes_t cnt);
+
+       // Shouldn't ever actually get called
+       static bool can_decode(QString filename) {return false;}
+
+protected:
+       nframes_t song_to_file_frame(nframes_t frame);
+       nframes_t file_to_song_frame(nframes_t frame);
+
+       AbstractAudioReader*    m_realReader;
+       SRC_STATE*      m_srcState;
+       SRC_DATA        m_srcData;
+       audio_sample_t  *m_fileBuffer;
+       long            m_fileBufferLength;
+};
+
+#endif

Index: SFAudioReader.cpp
===================================================================
RCS file: SFAudioReader.cpp
diff -N SFAudioReader.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ SFAudioReader.cpp   6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,145 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#include "SFAudioReader.h"
+#include <QFile>
+#include <QString>
+#include "Utils.h"
+
+// Always put me below _all_ includes, this is needed
+// in case we run with memory leak detection enabled!
+#include "Debugger.h"
+
+
+SFAudioReader::SFAudioReader(QString filename)
+ : AbstractAudioReader(filename)
+{
+       /* although libsndfile says we don't need to set this,
+       valgrind and source code shows us that we do.
+       Really? Look it up !
+       */
+       memset (&m_sfinfo, 0, sizeof(m_sfinfo));
+
+       if ((m_sf = sf_open ((m_fileName.toUtf8().data()), SFM_READ, 
&m_sfinfo)) == 0) {
+               PERROR("Couldn't open soundfile (%s)", QS_C(m_fileName));
+       }
+}
+
+
+SFAudioReader::~SFAudioReader()
+{
+       if (m_sf) {
+               if (sf_close(m_sf)) {
+                       qWarning("sf_close returned an error!");
+               }
+       }
+}
+
+
+bool SFAudioReader::can_decode(QString filename)
+{
+       SF_INFO infos;
+
+       /* although libsndfile says we don't need to set this,
+       valgrind and source code shows us that we do.
+       Really? Look it up !
+       */
+       memset (&infos, 0, sizeof(infos));
+
+       SNDFILE* sndfile = sf_open(QFile::encodeName(filename), SFM_READ, 
&infos);
+       
+       //is it supported by libsndfile?
+       if (!sndfile) {
+               return false;
+       }
+       
+       sf_close(sndfile);
+       
+       return true;
+}
+
+
+int SFAudioReader::get_num_channels()
+{
+       if (m_sf) {
+               return m_sfinfo.channels;
+       }
+       return 0;
+}
+
+
+int SFAudioReader::get_length()
+{
+       if (m_sf) {
+               return m_sfinfo.frames;
+       }
+       return 0;
+}
+
+
+int SFAudioReader::get_rate()
+{
+       if (m_sf) {
+               return m_sfinfo.samplerate;
+       }
+       return 0;
+}
+
+
+// Should this exist?  Should we just be smarter in MonoReader so we don't 
need this?
+bool SFAudioReader::is_compressed()
+{
+       return ((m_sfinfo.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC );
+}
+
+
+bool SFAudioReader::seek(nframes_t start)
+{
+       Q_ASSERT(m_sf);
+       
+       if (start >= get_length()) {
+               return false;
+       }
+       
+       if (sf_seek (m_sf, (off_t) start, SEEK_SET) < 0) {
+               char errbuf[256];
+               sf_error_str (0, errbuf, sizeof (errbuf) - 1);
+               PERROR("ReadAudioSource: could not seek to frame %d within %s 
(%s)", start, QS_C(m_fileName), errbuf);
+               return false;
+       }
+       
+       m_nextFrame = start;
+
+       return true;
+}
+
+
+int SFAudioReader::read(audio_sample_t* dst, nframes_t cnt)
+{
+       Q_ASSERT(m_sf);
+       
+       int samplesRead = sf_read_float (m_sf, dst, cnt);
+       
+       m_nextFrame += samplesRead / get_num_channels();
+       
+       return samplesRead;
+}
+

Index: SFAudioReader.h
===================================================================
RCS file: SFAudioReader.h
diff -N SFAudioReader.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ SFAudioReader.h     6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,49 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#ifndef SFAUDIOREADER_H
+#define SFAUDIOREADER_H
+
+#include <AbstractAudioReader.h>
+#include "sndfile.h"
+
+
+class SFAudioReader : public AbstractAudioReader
+{
+public:
+       SFAudioReader(QString filename);
+       ~SFAudioReader();
+
+       int get_num_channels();
+       int get_length();
+       int get_rate();
+       bool is_compressed();
+       bool seek(nframes_t start);
+       int read(audio_sample_t* dst, nframes_t cnt);
+
+       static bool can_decode(QString filename);
+
+protected:
+       SNDFILE*        m_sf;
+       SF_INFO         m_sfinfo;
+};
+
+#endif

Index: VorbisAudioReader.cpp
===================================================================
RCS file: VorbisAudioReader.cpp
diff -N VorbisAudioReader.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ VorbisAudioReader.cpp       6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,175 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#include "VorbisAudioReader.h"
+#include <QFile>
+#include <QString>
+#include "Utils.h"
+
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+// Always put me below _all_ includes, this is needed
+// in case we run with memory leak detection enabled!
+#include "Debugger.h"
+
+
+VorbisAudioReader::VorbisAudioReader(QString filename)
+ : AbstractAudioReader(filename)
+{
+       m_file = fopen(QFile::encodeName(filename), "r");
+       if (!m_file) {
+               PERROR("Couldn't open file %s.", QS_C(filename));
+               return;
+       }
+       
+       if (ov_open(m_file, &m_vf, NULL, 0) < 0) {
+               PERROR("Input does not appear to be an Ogg bitstream.");
+               return;
+       }
+
+       m_vi = ov_info(&m_vf,-1);
+}
+
+
+VorbisAudioReader::~VorbisAudioReader()
+{
+       if (m_file) {
+               ov_clear(&m_vf);
+               fclose(m_file);
+       }
+}
+
+
+bool VorbisAudioReader::can_decode(QString filename)
+{
+       FILE* file = fopen(QFile::encodeName(filename), "r");
+       if (!file) {
+               PERROR("Could not open file: %s.", QS_C(filename));
+               return false;
+       }
+       
+       OggVorbis_File of;
+       
+       if (ov_test(file, &of, 0, 0)) {
+               fclose(file);
+               return false;
+       }
+       
+       ov_clear(&of);
+       fclose(file);
+       
+       return true;
+}
+
+
+int VorbisAudioReader::get_num_channels()
+{
+       if (m_file) {
+               return m_vi->channels;
+       }
+       return 0;
+}
+
+
+int VorbisAudioReader::get_length()
+{
+       if (m_file) {
+               return ov_pcm_total(&m_vf, -1) / get_num_channels();
+       }
+       return 0;
+}
+
+
+int VorbisAudioReader::get_rate()
+{
+       if (m_file) {
+               return m_vi->rate;
+       }
+       return 0;
+}
+
+
+// Should this exist?  Should we just be smarter in MonoReader so we don't 
need this?
+bool VorbisAudioReader::is_compressed()
+{
+       return false;
+}
+
+
+bool VorbisAudioReader::seek(nframes_t start)
+{
+       Q_ASSERT(m_file);
+       
+       if (start >= get_length()) {
+               return false;
+       }
+       //printf("seek to %lu\n", start);
+       if (ov_pcm_seek(&m_vf, start) < 0) {
+               PERROR("VorbisAudioReader: could not seek to frame %d within 
%s", start, QS_C(m_fileName));
+               return false;
+       }
+       
+       m_nextFrame = start;
+
+       return true;
+}
+
+
+int VorbisAudioReader::read(audio_sample_t* dst, nframes_t cnt)
+{
+       Q_ASSERT(m_file);
+       
+       audio_sample_t** tmp;
+       int bs;
+       
+       int samplesRead = ov_read_float (&m_vf, &tmp, cnt, &bs);
+       
+       if (samplesRead == OV_HOLE) {
+               PERROR("VorbisAudioReader: OV_HOLE");
+               // recursive new try
+               return read(dst, cnt);
+       }
+       else if (samplesRead == 0) {
+               /* EOF */
+               return 0;
+       } else if (samplesRead < 0) {
+               /* error in the stream. */
+               return 0;
+       }
+       
+       int frames = samplesRead/get_num_channels();
+       for (int f=0; f < frames; f++) {
+               for (int c=0; c < get_num_channels(); c++) {
+                       dst[f * get_num_channels() + c] = tmp[c][f];
+               }
+       }
+       
+       //printf("SFAudioReader: cnt = %lu, samplesRead = %d, length = %lu\n", 
cnt, samplesRead, get_length());
+       
+       // m_nextFrame currently exists just for debugging
+       m_nextFrame += frames;
+       
+       return samplesRead;
+}
+

Index: VorbisAudioReader.h
===================================================================
RCS file: VorbisAudioReader.h
diff -N VorbisAudioReader.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ VorbisAudioReader.h 6 Jul 2007 22:13:32 -0000       1.1
@@ -0,0 +1,52 @@
+/*
+Copyright (C) 2007 Ben Levitt 
+
+This file is part of Traverso
+
+Traverso 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.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
+
+*/
+
+#ifndef VORBISAUDIOREADER_H
+#define VORBISAUDIOREADER_H
+
+#include "AbstractAudioReader.h"
+#include "vorbis/codec.h"
+#include "vorbis/vorbisfile.h"
+#include "stdio.h"
+
+
+class VorbisAudioReader : public AbstractAudioReader
+{
+public:
+       VorbisAudioReader(QString filename);
+       ~VorbisAudioReader();
+
+       int get_num_channels();
+       int get_length();
+       int get_rate();
+       bool is_compressed();
+       bool seek(nframes_t start);
+       int read(audio_sample_t* dst, nframes_t cnt);
+
+       static bool can_decode(QString filename);
+
+protected:
+       FILE*           m_file;
+       OggVorbis_File  m_vf;
+       vorbis_info*    m_vi;
+};
+
+#endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]