1 //----------------------------------------------------------------------------- 2 // Copyright (c) 2015-2018 Marcelo Fernandez 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to 6 // deal in the Software without restriction, including without limitation the 7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 // sell copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 // IN THE SOFTWARE. 21 //----------------------------------------------------------------------------- 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 #include "oamlCommon.h" 28 29 30 oamlAudioFile::oamlAudioFile(std::string _filename, oamlBase *_base, oamlFileCallbacks *cbs, bool _verbose) { 31 base = _base; 32 filename = _filename; 33 layer = ""; 34 randomChance = -1; 35 gain = 1.f; 36 fcbs = cbs; 37 verbose = _verbose; 38 39 #ifdef __HAVE_SOXR 40 soxr = NULL; 41 #endif 42 handle = NULL; 43 44 format = 0; 45 bytesPerSample = 0; 46 samplesPerSec = 0; 47 totalSamples = 0; 48 channelCount = 0; 49 samplesToEnd = 0; 50 fileBytesPerSample = 0; 51 main(int argc,char ** argv)52 chance = false; 53 lastChance = false; 54 } 55 56 oamlAudioFile::~oamlAudioFile() { 57 if (handle) { 58 delete handle; 59 handle = NULL; 60 } 61 62 #ifdef __HAVE_SOXR 63 if (soxr) { 64 soxr_delete(soxr); 65 soxr = NULL; 66 } 67 #endif 68 } 69 70 oamlRC oamlAudioFile::OpenFile() { 71 std::string ext = filename.substr(filename.find_last_of(".") + 1); 72 if (ext == "wav" || ext == "wave") { 73 handle = new wavFile(fcbs); 74 } else if (ext == "aif" || ext == "aiff") { 75 handle = (audioFile*)new aifFile(fcbs); 76 #ifdef __HAVE_OGG 77 } else if (ext == "ogg") { 78 handle = (audioFile*)new oggFile(fcbs); 79 #endif 80 } else { 81 fprintf(stderr, "liboaml: Unknown audio format: '%s'\n", GetFilenameStr()); 82 return OAML_ERROR; 83 } 84 85 if (handle->Open(GetFilenameStr()) == -1) { 86 fprintf(stderr, "liboaml: Error opening: '%s'\n", GetFilenameStr()); 87 return OAML_ERROR; 88 } 89 90 format = handle->GetFormat(); 91 bytesPerSample = handle->GetBytesPerSample(); 92 samplesPerSec = handle->GetSamplesPerSec(); 93 totalSamples = handle->GetTotalSamples(); 94 channelCount = handle->GetChannels(); 95 96 fileFormat = format; 97 fileBytesPerSample = bytesPerSample; 98 99 #ifdef __HAVE_SOXR 100 unsigned int sampleRate = base->GetSampleRate(); 101 if (sampleRate != samplesPerSec) { 102 if (soxr == NULL) { find_entry_for_token(char * token)103 soxr_io_spec_t spec; 104 105 switch (format) { 106 case AF_FORMAT_SINT8: 107 case AF_FORMAT_SINT16: 108 case AF_FORMAT_SINT24: 109 spec.itype = SOXR_INT16_I; 110 break; 111 112 case AF_FORMAT_SINT32: 113 spec.itype = SOXR_INT32_I; 114 break; 115 116 case AF_FORMAT_FLOAT32: 117 spec.itype = SOXR_FLOAT32_I; parse_line(char * line,SourceType type)118 break; 119 } 120 spec.otype = SOXR_INT16_I; 121 spec.scale = 1; 122 spec.e = NULL; 123 spec.flags = 0; 124 125 soxr = soxr_create(double(samplesPerSec), double(sampleRate), channelCount, NULL, &spec, NULL, NULL); 126 } 127 128 totalSamples = (double)totalSamples * sampleRate / samplesPerSec; 129 samplesToEnd = (double)samplesToEnd * sampleRate / samplesPerSec; 130 samplesPerSec = sampleRate; 131 format = AF_FORMAT_SINT16; 132 bytesPerSample = 2; 133 } 134 #endif 135 136 return OAML_OK; 137 } 138 139 oamlRC oamlAudioFile::Open() { 140 if (verbose) __oamlLog("%s %s\n", __FUNCTION__, GetFilenameStr()); 141 if (buffer.size() == 0) { 142 oamlRC rc = OpenFile(); 143 if (rc != OAML_OK) return rc; 144 } 145 146 if (GetRandomChance() != -1) { 147 chance = __oamlRandom(0, 100) > GetRandomChance(); 148 } else { parse_contents(FILE * stream,SourceType type)149 lastChance = true; 150 chance = true; 151 } 152 153 return OAML_OK; 154 } 155 156 oamlRC oamlAudioFile::Load() { 157 int ret; 158 do { 159 ret = Read(); 160 } while (ret > 0); 161 162 if (ret == -1) return OAML_ERROR; 163 return OAML_OK; 164 } 165 166 int oamlAudioFile::LoadProgress() { 167 if (handle == NULL) { 168 return buffer.size()/bytesPerSample; 169 } 170 171 int ret = Read(); 172 if (ret == -1) { 173 return -1; 174 } 175 176 return buffer.size()/bytesPerSample; 177 } 178 179 int oamlAudioFile::Read() { 180 if (handle == NULL) 181 return -1; 182 183 char buf[4096]; 184 int frames = 4096 / fileBytesPerSample / channelCount; 185 int readSize = frames * fileBytesPerSample * channelCount; 186 int bytes = handle->Read(buf, readSize); 187 if (bytes <= 0) { 188 handle->Close(); 189 delete handle; 190 handle = NULL; 191 } 192 193 #ifdef __HAVE_SOXR 194 if (soxr != NULL) { 195 // Re-sample through libsoxr 196 char obuf[4096*4]; 197 198 size_t ilen = bytes / fileBytesPerSample / channelCount; 199 size_t idone = 0; 200 size_t olen = 4096*4 / bytesPerSample / channelCount; 201 size_t odone = 0; 202 soxr_error_t err; 203 204 switch (fileFormat) { 205 case AF_FORMAT_SINT8: 206 // 8-bit is not directly supported by libsoxr, convert the buffer to 16-bit and then process 207 { 208 int16_t buf16[4096]; 209 for (int i=0; i<bytes; i++) { 210 buf16[i] = (int16_t)buf[i] << 8; 211 } 212 213 err = soxr_process(soxr, (char*)buf16, ilen, &idone, obuf, olen, &odone); 214 } 215 break; 216 217 case AF_FORMAT_SINT24: 218 // 24-bit is not directly supported by libsoxr, convert the buffer to 16-bit and then process 219 { 220 int16_t buf16[4096]; 221 for (int i=0; i<bytes/3; i++) { 222 buf16[i] = (((int16_t)buf[i*3+2] & 0xFF) << 8) | ((int16_t)buf[i*3+1] & 0xFF); 223 } 224 225 err = soxr_process(soxr, (char*)buf16, ilen, &idone, obuf, olen, &odone); 226 } 227 break; 228 229 default: 230 // Input format is supported by libsoxr, process out buffers 231 err = soxr_process(soxr, buf, ilen, &idone, obuf, olen, &odone); 232 break; 233 } 234 235 if (err != NULL) { 236 fprintf(stderr, "liboaml: Error on soxr_process\n"); 237 return -1; 238 } else if (odone > 0) { 239 buffer.putBytes((uint8_t*)obuf, odone * bytesPerSample * channelCount); 240 } 241 242 return odone; 243 } 244 #endif 245 246 if (bytes > 0) { 247 buffer.putBytes((uint8_t*)buf, bytes); 248 } 249 250 return bytes; 251 } 252 253 int oamlAudioFile::Read32(unsigned int pos) { 254 int ret = 0; 255 256 if (pos > totalSamples) 257 return 0; 258 259 pos*= bytesPerSample; 260 while ((pos+bytesPerSample) > buffer.size()) { 261 if (Read() == -1) 262 return 0; 263 } 264 265 switch (format) { 266 case AF_FORMAT_FLOAT32: 267 ret|= ((uint32_t)buffer.get(pos)); 268 ret|= ((uint32_t)buffer.get(pos+1))<<8; 269 ret|= ((uint32_t)buffer.get(pos+2))<<16; 270 ret|= ((uint32_t)buffer.get(pos+3))<<24; 271 ret = uint32_t(*(float*)&ret * 32768.f) << 16; 272 break; 273 274 case AF_FORMAT_SINT32: 275 break; 276 277 case AF_FORMAT_SINT24: 278 ret|= ((uint32_t)buffer.get(pos))<<8; 279 ret|= ((uint32_t)buffer.get(pos+1))<<16; 280 ret|= ((uint32_t)buffer.get(pos+2))<<24; 281 break; 282 283 case AF_FORMAT_SINT16: 284 ret|= ((uint32_t)buffer.get(pos))<<16; 285 ret|= ((uint32_t)buffer.get(pos+1))<<24; 286 break; 287 288 case AF_FORMAT_SINT8: 289 ret|= ((uint32_t)buffer.get(pos))<<23; 290 break; 291 } 292 293 return ret; 294 } 295 296 float oamlAudioFile::ReadFloat(unsigned int pos, bool isTail) { 297 if (isTail) { 298 if (lastChance == false) 299 return 0.f; 300 } else { 301 if (pos == (samplesToEnd-1)) { 302 lastChance = chance; 303 } 304 305 if (chance == false) 306 return 0.f; 307 } 308 309 float sample = __oamlInteger24ToFloat(Read32(pos)>>8); 310 if (GetGain() != 1.f) { 311 sample*= GetGain(); 312 } 313 return sample; 314 } 315 316 void oamlAudioFile::FreeMemory() { 317 if (buffer.size() > 0 || handle != NULL) { 318 if (verbose) __oamlLog("%s %s\n", __FUNCTION__, GetFilenameStr()); 319 } 320 321 buffer.clear(); 322 buffer.free(); 323 324 if (handle) { 325 delete handle; 326 handle = NULL; 327 } 328 329 format = 0; 330 bytesPerSample = 0; 331 samplesPerSec = 0; 332 totalSamples = 0; 333 channelCount = 0; 334 } 335