1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 /* 4 Rosegarden 5 A sequencer and musical notation editor. 6 Copyright 2000-2021 the Rosegarden development team. 7 See the AUTHORS file for more details. 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 RG_PLAYABLE_AUDIO_FILE_H 17 #define RG_PLAYABLE_AUDIO_FILE_H 18 19 #include "base/Instrument.h" 20 #include "RingBuffer.h" 21 #include "AudioFile.h" 22 #include "AudioCache.h" 23 24 #include <string> 25 #include <map> 26 27 namespace Rosegarden 28 { 29 30 class RingBufferPool; 31 32 33 class PlayableAudioFile 34 { 35 public: 36 typedef float sample_t; 37 38 PlayableAudioFile(InstrumentId instrumentId, 39 AudioFile *audioFile, 40 const RealTime &startTime, 41 const RealTime &startIndex, 42 const RealTime &duration, 43 size_t bufferSize = 4096, 44 size_t smallFileSize = 131072, 45 int targetChannels = -1, // default same as file 46 int targetSampleRate = -1); // default same as file 47 ~PlayableAudioFile(); 48 49 static void setRingBufferPoolSizes(size_t n, size_t nframes); 50 setStartTime(const RealTime & time)51 void setStartTime(const RealTime &time) { m_startTime = time; } getStartTime()52 RealTime getStartTime() const { return m_startTime; } 53 setDuration(const RealTime & time)54 void setDuration(const RealTime &time) { m_duration = time; } getDuration()55 RealTime getDuration() const { return m_duration; } getEndTime()56 RealTime getEndTime() const { return m_startTime + m_duration; } 57 setStartIndex(const RealTime & time)58 void setStartIndex(const RealTime &time) { m_startIndex = time; } getStartIndex()59 RealTime getStartIndex() const { return m_startIndex; } 60 isSmallFile()61 bool isSmallFile() const { return m_isSmallFile; } 62 63 // Get audio file for interrogation 64 // getAudioFile()65 AudioFile* getAudioFile() const { return m_audioFile; } 66 67 // Get instrument ID - we need to be able to map back 68 // at the GUI. 69 // getInstrument()70 InstrumentId getInstrument() const { return m_instrumentId; } 71 72 // Return the number of frames currently buffered. The next call 73 // to getSamples on any channel is guaranteed to return at least 74 // this many samples. 75 // 76 size_t getSampleFramesAvailable(); 77 78 // Read samples from the given channel on the file and add them 79 // into the destination. 80 // 81 // If insufficient frames are available, this will leave the 82 // excess samples unchanged. 83 // 84 // Returns the actual number of samples written. 85 // 86 // If offset is non-zero, the samples will be written starting at 87 // offset frames from the start of the target block. 88 // 89 size_t addSamples(std::vector<sample_t *> &target, 90 size_t channels, size_t nframes, size_t offset = 0); 91 92 unsigned int getSourceChannels(); 93 unsigned int getTargetChannels(); 94 unsigned int getSourceSampleRate(); 95 unsigned int getTargetSampleRate(); 96 97 unsigned int getBitsPerSample(); 98 unsigned int getBytesPerFrame(); 99 100 // Clear out and refill the ring buffer for immediate 101 // (asynchronous) play. 102 // 103 void fillBuffers(); 104 105 // Clear out and refill the ring buffer (in preparation for 106 // playback) according to the proposed play time. 107 // 108 // This call and updateBuffers are not thread-safe (for 109 // performance reasons). They should be called for all files 110 // sequentially within a single thread. 111 // 112 bool fillBuffers(const RealTime ¤tTime); 113 114 void clearBuffers(); 115 116 // Update the buffer during playback. 117 // 118 // This call and fillBuffers are not thread-safe (for performance 119 // reasons). They should be called for all files sequentially 120 // within a single thread. 121 // 122 bool updateBuffers(); 123 124 // Has fillBuffers been called and completed yet? 125 // isBuffered()126 bool isBuffered() const { return m_currentScanPoint > m_startIndex; } 127 128 // Has all the data in this file now been read into the buffers? 129 // isFullyBuffered()130 bool isFullyBuffered() const { return m_isSmallFile || m_fileEnded; } 131 132 // Stop playing this file. 133 // cancel()134 void cancel() { m_fileEnded = true; } 135 136 // Segment id that allows us to crosscheck against playing audio 137 // segments. 138 // getRuntimeSegmentId()139 int getRuntimeSegmentId() const { return m_runtimeSegmentId; } setRuntimeSegmentId(int id)140 void setRuntimeSegmentId(int id) { m_runtimeSegmentId = id; } 141 142 // Auto fading of a playable audio file 143 // isAutoFading()144 bool isAutoFading() const { return m_autoFade; } setAutoFade(bool value)145 void setAutoFade(bool value) { m_autoFade = value; } 146 getFadeInTime()147 RealTime getFadeInTime() const { return m_fadeInTime; } setFadeInTime(const RealTime & time)148 void setFadeInTime(const RealTime &time) 149 { m_fadeInTime = time; } 150 getFadeOutTime()151 RealTime getFadeOutTime() const { return m_fadeOutTime; } setFadeOutTime(const RealTime & time)152 void setFadeOutTime(const RealTime &time) 153 { m_fadeOutTime = time; } 154 155 156 protected: 157 void initialise(size_t bufferSize, size_t smallFileSize); 158 void checkSmallFileCache(size_t smallFileSize); 159 bool scanTo(const RealTime &time); 160 void returnRingBuffers(); 161 162 RealTime m_startTime; 163 RealTime m_startIndex; 164 RealTime m_duration; 165 166 // Performance file handle - must open non-blocking to 167 // allow other potential PlayableAudioFiles access to 168 // the same file. 169 // 170 std::ifstream *m_file; 171 172 // AudioFile handle 173 // 174 AudioFile *m_audioFile; 175 176 // Originating Instrument Id 177 // 178 InstrumentId m_instrumentId; 179 180 int m_targetChannels; 181 int m_targetSampleRate; 182 183 bool m_fileEnded; 184 bool m_firstRead; 185 static size_t m_xfadeFrames; 186 int m_runtimeSegmentId; 187 188 static AudioCache m_smallFileCache; 189 bool m_isSmallFile; 190 191 static std::vector<sample_t *> m_workBuffers; 192 static size_t m_workBufferSize; 193 194 static char *m_rawFileBuffer; 195 static size_t m_rawFileBufferSize; 196 197 RingBuffer<sample_t> **m_ringBuffers; 198 static RingBufferPool *m_ringBufferPool; 199 200 RealTime m_currentScanPoint; 201 size_t m_smallFileScanFrame; 202 203 bool m_autoFade; 204 RealTime m_fadeInTime; 205 RealTime m_fadeOutTime; 206 207 private: 208 PlayableAudioFile(const PlayableAudioFile &pAF); // not provided 209 }; 210 211 } 212 213 #endif 214