1 /******************************************************************************* 2 * Copyright 2015-2016 Juan Francisco Crespo Galán 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 #pragma once 18 19 /** 20 * @file BinauralReader.h 21 * @ingroup fx 22 * The BinauralReader class. 23 */ 24 25 #include "IReader.h" 26 #include "ISound.h" 27 #include "Convolver.h" 28 #include "HRTF.h" 29 #include "Source.h" 30 #include "util/FFTPlan.h" 31 #include "util/ThreadPool.h" 32 33 #include <memory> 34 #include <vector> 35 #include <future> 36 37 AUD_NAMESPACE_BEGIN 38 39 /** 40 * This class represents a reader for a sound that can sound different depending on its realtive position with the listener. 41 */ 42 class AUD_API BinauralReader : public IReader 43 { 44 private: 45 /** 46 * The current position. 47 */ 48 int m_position; 49 50 /** 51 * The reader of the input sound. 52 */ 53 std::shared_ptr<IReader> m_reader; 54 55 /** 56 * The HRTF set. 57 */ 58 std::shared_ptr<HRTF> m_hrtfs; 59 60 /** 61 * A Source object that will be used to change the source position of the sound. 62 */ 63 std::shared_ptr<Source> m_source; 64 65 /** 66 * The intended azimuth. 67 */ 68 float m_Azimuth; 69 70 /** 71 * The intended elevation. 72 */ 73 float m_Elevation; 74 75 /** 76 * The real azimuth being used. 77 */ 78 float m_RealAzimuth; 79 80 /** 81 * The real elevation being used. 82 */ 83 float m_RealElevation; 84 85 /** 86 * The FFT size, given by the FFTPlan. 87 */ 88 int m_N; 89 90 /** 91 * The length of the impulse response fragments, m_N/2 will be used. 92 */ 93 int m_M; 94 95 /** 96 * The max length of the input slices, m_N/2 will be used. 97 */ 98 int m_L; 99 100 /** 101 * The array of convolvers that will be used, one per channel. 102 */ 103 std::vector<std::unique_ptr<Convolver>> m_convolvers; 104 105 /** 106 * True if a transition is happening. 107 */ 108 bool m_transition; 109 110 /** 111 * The position of the current transition (decreasing) 112 */ 113 int m_transPos; 114 115 /** 116 * The output buffer in which the convolved data will be written and from which the reader will read. 117 */ 118 sample_t* m_outBuffer; 119 120 /** 121 * The input buffer that will hold the data to be convolved. 122 */ 123 sample_t* m_inBuffer; 124 125 /** 126 * Current position in which the m_outBuffer is being read. 127 */ 128 int m_outBufferPos; 129 130 /** 131 * Length of rhe m_outBuffer. 132 */ 133 int m_outBufLen; 134 135 /** 136 * Effective length of rhe m_outBuffer. 137 */ 138 int m_eOutBufLen; 139 140 /** 141 * Flag indicating whether the end of the sound has been reached or not. 142 */ 143 bool m_eosReader; 144 145 /** 146 * Flag indicating whether the end of the extra data generated in the convolution has been reached or not. 147 */ 148 bool m_eosTail; 149 150 /** 151 * A vector of buffers (one per channel) on which the audio signal will be separated per channel so it can be convolved. 152 */ 153 std::vector<sample_t*> m_vecOut; 154 155 /** 156 * A shared ptr to a thread pool. 157 */ 158 std::shared_ptr<ThreadPool> m_threadPool; 159 160 /** 161 * Length of the input data to be used by the channel threads. 162 */ 163 int m_lastLengthIn; 164 165 /** 166 * A vector of futures to sync tasks. 167 */ 168 std::vector<std::future<int>> m_futures; 169 170 // delete copy constructor and operator= 171 BinauralReader(const BinauralReader&) = delete; 172 BinauralReader& operator=(const BinauralReader&) = delete; 173 174 public: 175 /** 176 * Creates a new convolver reader. 177 * \param reader A reader of the input sound to be assigned to this reader. It must have one channel. 178 * \param hrtfs A shared pointer to an HRTF object that will be used to get a particular impulse response depending on the source. 179 * \param source A shared pointer to a Source object that will be used to change the source position of the sound. 180 * \param threadPool A shared pointer to a ThreadPool object with 1 or more threads. 181 * \param plan A shared pointer to and FFT plan that will be used for convolution. 182 * \exception Exception thrown if the specs of the HRTFs and the sound don't match or if the provided HRTF object is empty. 183 */ 184 BinauralReader(std::shared_ptr<IReader> reader, std::shared_ptr<HRTF> hrtfs, std::shared_ptr<Source> source, std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<FFTPlan> plan); 185 virtual ~BinauralReader(); 186 187 virtual bool isSeekable() const; 188 virtual void seek(int position); 189 virtual int getLength() const; 190 virtual int getPosition() const; 191 virtual Specs getSpecs() const; 192 virtual void read(int& length, bool& eos, sample_t* buffer); 193 194 private: 195 /** 196 * Joins several buffers (one per channel) into the m_outBuffer. 197 * \param start The starting position from which the m_outBuffer will be written. 198 * \param len The amout of samples that will be joined. 199 * \param nConvolvers The number of convolvers that have been used. Only use 2 or 4 as possible values. 200 If the value is 4 the result will be interpolated. 201 */ 202 void joinByChannel(int start, int len, int nConvolvers); 203 204 /** 205 * Loads the m_outBuffer with data. 206 * \param nConvolvers The number of convolver objects that will be used. Only 2 or 4 should be used. 207 */ 208 void loadBuffer(int nConvolvers); 209 210 /** 211 * The function that the threads will run. It will process a subset of channels. 212 * \param id An id number that will determine which subset of channels will be processed. 213 * \param input A flag that will indicate if thare is input data. 214 * -If true there is new input data. 215 * -If false there isn't new input data. 216 * \return The number of samples obtained. 217 */ 218 int threadFunction(int id, bool input); 219 220 bool checkSource(); 221 }; 222 223 AUD_NAMESPACE_END