1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Sonic Visualiser
5     An audio file viewer and annotation editor.
6     Centre for Digital Music, Queen Mary, University of London.
7     This file copyright 2006 Chris Cannam.
8 
9     This program is free software; you can redistribute it and/or
10     modify it under the terms of the GNU General Public License as
11     published by the Free Software Foundation; either version 2 of the
12     License, or (at your option) any later version.  See the file
13     COPYING included with this distribution for more information.
14 */
15 
16 #ifndef SV_CODED_AUDIO_FILE_READER_H
17 #define SV_CODED_AUDIO_FILE_READER_H
18 
19 #include "AudioFileReader.h"
20 
21 #include <QMutex>
22 #include <QReadWriteLock>
23 
24 #ifdef Q_OS_WIN
25 #include <windows.h>
26 #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
27 #endif
28 
29 #include <sndfile.h>
30 
31 class WavFileReader;
32 class Serialiser;
33 
34 namespace breakfastquay {
35     class Resampler;
36 }
37 
38 class CodedAudioFileReader : public AudioFileReader
39 {
40     Q_OBJECT
41 
42 public:
43     virtual ~CodedAudioFileReader();
44 
45     enum CacheMode {
46         CacheInTemporaryFile,
47         CacheInMemory
48     };
49 
50     enum DecodeMode {
51         DecodeAtOnce, // decode the file on construction, with progress
52         DecodeThreaded // decode in a background thread after construction
53     };
54 
55     floatvec_t getInterleavedFrames(sv_frame_t start, sv_frame_t count) const override;
56 
getNativeRate()57     sv_samplerate_t getNativeRate() const override { return m_fileRate; }
58 
getLocalFilename()59     QString getLocalFilename() const override { return m_cacheFileName; }
60 
61     /// Intermediate cache means all CodedAudioFileReaders are quickly seekable
isQuicklySeekable()62     bool isQuicklySeekable() const override { return true; }
63 
64 signals:
65     void progress(int);
66 
67 protected:
68     CodedAudioFileReader(CacheMode cacheMode,
69                          sv_samplerate_t targetRate,
70                          bool normalised);
71 
72     void initialiseDecodeCache(); // samplerate, channels must have been set
73 
74     // compensation for encoder delays:
75     void setFramesToTrim(sv_frame_t fromStart, sv_frame_t fromEnd);
76 
77     // may throw InsufficientDiscSpace:
78     void addSamplesToDecodeCache(float **samples, sv_frame_t nframes);
79     void addSamplesToDecodeCache(float *samplesInterleaved, sv_frame_t nframes);
80     void addSamplesToDecodeCache(const floatvec_t &interleaved);
81 
82     // may throw InsufficientDiscSpace:
83     void finishDecodeCache();
84 
isDecodeCacheInitialised()85     bool isDecodeCacheInitialised() const { return m_initialised; }
86 
87     void startSerialised(QString id);
88     void endSerialised();
89 
90 private:
91     void pushCacheWriteBufferMaybe(bool final);
92 
93     sv_frame_t pushBuffer(float *interleaved, sv_frame_t sz, bool final);
94 
95     // to be called only by pushBuffer
96     void pushBufferResampling(float *interleaved, sv_frame_t sz, double ratio, bool final);
97 
98     // to be called only by pushBuffer and pushBufferResampling
99     void pushBufferNonResampling(float *interleaved, sv_frame_t sz);
100 
101 protected:
102     QMutex m_cacheMutex;
103     CacheMode m_cacheMode;
104     floatvec_t m_data;
105     mutable QMutex m_dataLock;
106     bool m_initialised;
107     Serialiser *m_serialiser;
108     sv_samplerate_t m_fileRate;
109 
110     QString m_cacheFileName;
111     SNDFILE *m_cacheFileWritePtr;
112     WavFileReader *m_cacheFileReader;
113     float *m_cacheWriteBuffer;
114     sv_frame_t m_cacheWriteBufferIndex;  // buffer write pointer in samples
115     sv_frame_t m_cacheWriteBufferFrames; // buffer size in frames
116 
117     breakfastquay::Resampler *m_resampler;
118     float *m_resampleBuffer;
119     int m_resampleBufferFrames;
120     sv_frame_t m_fileFrameCount;
121 
122     bool m_normalised;
123     float m_max;
124     float m_gain;
125 
126     sv_frame_t m_trimFromStart;
127     sv_frame_t m_trimFromEnd;
128 
129     sv_frame_t m_clippedCount;
130     sv_frame_t m_firstNonzero;
131     sv_frame_t m_lastNonzero;
132 };
133 
134 #endif
135