1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 28 янв. 2016 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #include <dsp/dsp.h> 23 #include <dsp/endian.h> 24 #include <core/types.h> 25 #include <core/debug.h> 26 #include <core/files/LSPCFile.h> 27 #include <core/files/AudioFile.h> 28 #include <core/files/lspc/LSPCAudioReader.h> 29 #include <core/alloc.h> 30 31 #ifdef PLATFORM_WINDOWS 32 /* 33 Need to implement MMIO support 34 https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/directshow/dmo/dmodemo/wave.c 35 */ 36 37 #include <shtypes.h> 38 #include <shlwapi.h> 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 #include <propvarutil.h> 43 #ifdef __cplusplus 44 } 45 #endif 46 47 #include <guiddef.h> 48 #include <propidl.h> 49 #include <propvarutil.h> 50 #include <mfapi.h> 51 #include <mfidl.h> 52 #include <mferror.h> 53 #include <mfreadwrite.h> 54 55 #include <mmsystem.h> 56 #include <msacm.h> 57 58 // Define some missing values from GNU <mfidl.h> 59 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 60 EXTERN_GUID( MF_TRANSCODE_CONTAINERTYPE, 0x150ff23f, 0x4abc, 0x478b, 0xac, 0x4f, 0xe1, 0x91, 0x6f, 0xba, 0x1c, 0xca ); 61 EXTERN_GUID( MFTranscodeContainerType_ASF, 0x430f6f6e, 0xb6bf, 0x4fc1, 0xa0, 0xbd, 0x9e, 0xe4, 0x6e, 0xee, 0x2a, 0xfb ); 62 EXTERN_GUID( MFTranscodeContainerType_MPEG4, 0xdc6cd05d, 0xb9d0, 0x40ef, 0xbd, 0x35, 0xfa, 0x62, 0x2c, 0x1a, 0xb2, 0x8a ); 63 EXTERN_GUID( MFTranscodeContainerType_MP3, 0xe438b912, 0x83f1, 0x4de6, 0x9e, 0x3a, 0x9f, 0xfb, 0xc6, 0xdd, 0x24, 0xd1 ); 64 EXTERN_GUID( MFTranscodeContainerType_FLAC, 0x31344aa3, 0x05a9, 0x42b5, 0x90, 0x1b, 0x8e, 0x9d, 0x42, 0x57, 0xf7, 0x5e ); 65 EXTERN_GUID( MFTranscodeContainerType_3GP, 0x34c50167, 0x4472, 0x4f34, 0x9e, 0xa0, 0xc4, 0x9f, 0xba, 0xcf, 0x03, 0x7d ); 66 EXTERN_GUID( MFTranscodeContainerType_AC3, 0x6d8d91c3, 0x8c91, 0x4ed1, 0x87, 0x42, 0x8c, 0x34, 0x7d, 0x5b, 0x44, 0xd0 ); 67 EXTERN_GUID( MFTranscodeContainerType_ADTS, 0x132fd27d, 0x0f02, 0x43de, 0xa3, 0x01, 0x38, 0xfb, 0xbb, 0xb3, 0x83, 0x4e ); 68 EXTERN_GUID( MFTranscodeContainerType_MPEG2, 0xbfc2dbf9, 0x7bb4, 0x4f8f, 0xaf, 0xde, 0xe1, 0x12, 0xc4, 0x4b, 0xa8, 0x82 ); 69 EXTERN_GUID( MFTranscodeContainerType_WAVE, 0x64c3453c, 0x0f26, 0x4741, 0xbe, 0x63, 0x87, 0xbd, 0xf8, 0xbb, 0x93, 0x5b ); 70 EXTERN_GUID( MFTranscodeContainerType_AVI, 0x7edfe8af, 0x402f, 0x4d76, 0xa3, 0x3c, 0x61, 0x9f, 0xd1, 0x57, 0xd0, 0xf1 ); 71 72 #if (WINVER >= _WIN32_WINNT_WIN8) 73 EXTERN_GUID( MFTranscodeContainerType_FMPEG4, 0x9ba876f1, 0x419f, 0x4b77, 0xa1, 0xe0, 0x35, 0x95, 0x9d, 0x9d, 0x40, 0x4 ); 74 #endif // (WINVER >= _WIN32_WINNT_WIN8) 75 76 EXTERN_GUID( MFTranscodeContainerType_AMR, 0x25d5ad3, 0x621a, 0x475b, 0x96, 0x4d, 0x66, 0xb1, 0xc8, 0x24, 0xf0, 0x79 ); 77 #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */ 78 79 #else 80 #include <sndfile.h> 81 #endif /* PLATFORM_WINDOWS */ 82 83 #define TMP_BUFFER_SIZE 1024 84 #define RESAMPLING_PERIODS 8 85 #define ACM_INPUT_BUFSIZE 0x1000 86 87 namespace lsp 88 { gcd_euclid(size_t a,size_t b)89 static size_t gcd_euclid(size_t a, size_t b) 90 { 91 while (b) 92 { 93 size_t c = a % b; 94 a = b; 95 b = c; 96 } 97 return a; 98 } 99 AudioFile()100 AudioFile::AudioFile() 101 { 102 pData = NULL; 103 } 104 ~AudioFile()105 AudioFile::~AudioFile() 106 { 107 destroy(); 108 } 109 destroy()110 void AudioFile::destroy() 111 { 112 lsp_trace("Destroy this=%p, pData=%p", this, pData); 113 if (pData != NULL) 114 { 115 destroy_file_content(pData); 116 pData = NULL; 117 } 118 } 119 create_file_content(size_t channels,size_t samples)120 AudioFile::file_content_t *AudioFile::create_file_content(size_t channels, size_t samples) 121 { 122 // Make number of samples multiple of 0x20 bytes 123 size_t buffer_len = (samples + 0x03) & (~size_t(0x03)); 124 size_t buffer_size = (buffer_len * sizeof(float) + 0x1f) & (~size_t(0x1f)); // +3 - for convolution alignment 125 // Make header size multiple of 0x20 bytes 126 size_t header_size = (sizeof(file_content_t) + sizeof(float *) * channels + 0x1f) & (~size_t(0x1f)); 127 // Calculate total size 128 size_t total_size = header_size + buffer_size * channels; 129 130 // Allocate structure 131 uint8_t *ptr = lsp_tmalloc(uint8_t, total_size); 132 if (ptr == NULL) 133 return NULL; 134 135 // Initialize content 136 file_content_t *ct = reinterpret_cast<file_content_t *>(ptr); 137 ct->nChannels = channels; 138 ct->nSamples = buffer_len; 139 ct->nSampleRate = 0; 140 ptr += header_size; 141 142 for (size_t i=0; i < channels; ++i) 143 { 144 ct->vChannels[i] = reinterpret_cast<float *>(ptr); 145 dsp::fill_zero(ct->vChannels[i], buffer_len); 146 147 ptr += buffer_size; 148 } 149 150 return ct; 151 } 152 grow_file_content(file_content_t * src,size_t samples)153 AudioFile::file_content_t *AudioFile::grow_file_content(file_content_t *src, size_t samples) 154 { 155 // We have enough space to store samples? 156 if (src->nSamples >= samples) 157 return src; 158 159 // Allocate new file content 160 size_t new_cap = src->nSamples + (src->nSamples >> 1); 161 if (new_cap < samples) 162 new_cap = samples + (samples >> 1); 163 file_content_t *dst = create_file_content(src->nSamples, new_cap); 164 if (dst == NULL) 165 return NULL; 166 167 // Copy data from previous file content 168 for (size_t i=0; i < src->nChannels; ++i) 169 dsp::copy(dst->vChannels[i], src->vChannels[i], src->nSamples); 170 171 // Drop previously used content and return new content 172 destroy_file_content(src); 173 return dst; 174 } 175 destroy_file_content(file_content_t * content)176 void AudioFile::destroy_file_content(file_content_t *content) 177 { 178 if (content != NULL) 179 lsp_free(content); 180 } 181 create_temporary_buffer(file_content_t * content,size_t from)182 AudioFile::temporary_buffer_t *AudioFile::create_temporary_buffer(file_content_t *content, size_t from) 183 { 184 // Make number of samples multiple of 0x20 bytes 185 size_t buffer_bytes = content->nChannels * TMP_BUFFER_SIZE * sizeof(float); 186 size_t buffer_size = ALIGN_SIZE(buffer_bytes, 0x20); 187 // Make header size multiple of 0x20 bytes 188 size_t header_size = ALIGN_SIZE(sizeof(temporary_buffer_t) + sizeof(float *) * content->nChannels, 0x20); 189 // Calculate total size 190 size_t total_size = header_size + buffer_size; 191 192 // Allocate structure 193 uint8_t *ptr = lsp_tmalloc(uint8_t, total_size); 194 if (ptr == NULL) 195 return NULL; 196 197 // Initialize structure 198 temporary_buffer_t *tb = reinterpret_cast<temporary_buffer_t *>(ptr); 199 ptr += header_size; 200 201 tb->nSize = 0; 202 tb->nCapacity = buffer_bytes; 203 tb->nFrameSize = content->nChannels * sizeof(float); 204 tb->nChannels = content->nChannels; 205 tb->bData = ptr; 206 for (size_t i=0; i<content->nChannels; ++i) 207 { 208 float *chPtr = content->vChannels[i]; 209 tb->vChannels[i] = &chPtr[from]; 210 } 211 212 return tb; 213 } 214 flush_temporary_buffer(temporary_buffer_t * tb)215 void AudioFile::flush_temporary_buffer(temporary_buffer_t *tb) 216 { 217 // Estimate number of bytes in buffer 218 size_t avail = tb->nSize; 219 float *src = reinterpret_cast<float *>(tb->bData); 220 221 // Process all fully-read frames 222 while (avail >= tb->nFrameSize) 223 { 224 // Decode frame 225 for (size_t i=0; i<tb->nChannels; ++i) 226 *(tb->vChannels[i]++) = *(src++); 227 avail -= tb->nFrameSize; 228 } 229 230 // Update buffer contents 231 if (avail > 0) 232 ::memmove(tb->bData, src, avail); 233 tb->nSize = avail; 234 } 235 fill_temporary_buffer(temporary_buffer_t * tb,size_t max_samples)236 size_t AudioFile::fill_temporary_buffer(temporary_buffer_t *tb, size_t max_samples) 237 { 238 size_t avail = tb->nCapacity - tb->nSize; 239 size_t count = 0; 240 float *dst = reinterpret_cast<float *>(&tb->bData[tb->nSize]); 241 242 while ((avail >= tb->nFrameSize) && (count < max_samples)) 243 { 244 // Encode frame 245 for (size_t i=0; i<tb->nChannels; ++i) 246 *(dst++) = *(tb->vChannels[i]++); 247 avail -= tb->nFrameSize; 248 ++count; 249 } 250 251 tb->nSize = tb->nCapacity - avail; 252 return count; 253 } 254 destroy_temporary_buffer(temporary_buffer_t * buffer)255 void AudioFile::destroy_temporary_buffer(temporary_buffer_t *buffer) 256 { 257 if (buffer != NULL) 258 lsp_free(buffer); 259 } 260 create_samples(size_t channels,size_t sample_rate,size_t count)261 status_t AudioFile::create_samples(size_t channels, size_t sample_rate, size_t count) 262 { 263 // Allocate content 264 file_content_t *fc = create_file_content(channels, count); 265 if (fc == NULL) 266 return STATUS_NO_MEM; 267 268 // Cleanup content 269 fc->nSampleRate = sample_rate; 270 for (size_t i=0; i<channels; ++i) 271 dsp::fill_zero(fc->vChannels[i], count); 272 273 // Destroy previously used content and store new 274 if (pData != NULL) 275 destroy_file_content(pData); 276 pData = fc; 277 return STATUS_OK; 278 } 279 create(const Sample * sample,size_t sample_rate)280 status_t AudioFile::create(const Sample *sample, size_t sample_rate) 281 { 282 if (sample == NULL) 283 return STATUS_BAD_ARGUMENTS; 284 285 // Allocate content 286 size_t channels = sample->channels(); 287 size_t length = sample->length(); 288 file_content_t *fc = create_file_content(channels, length); 289 if (fc == NULL) 290 return STATUS_NO_MEM; 291 292 // Cleanup content 293 fc->nSampleRate = sample_rate; 294 for (size_t i=0; i<channels; ++i) 295 dsp::copy(fc->vChannels[i], sample->getBuffer(i), length); 296 297 // Destroy previously used content and store new 298 if (pData != NULL) 299 destroy_file_content(pData); 300 pData = fc; 301 return STATUS_OK; 302 } 303 create(size_t channels,size_t sample_rate,float duration)304 status_t AudioFile::create(size_t channels, size_t sample_rate, float duration) 305 { 306 // Calculate the file length (in samples) and call the previous method 307 size_t count = sample_rate * duration; 308 return create_samples(channels, sample_rate, count); 309 } 310 load_lspc(const LSPString * path,float max_duration)311 status_t AudioFile::load_lspc(const LSPString *path, float max_duration) 312 { 313 LSPCFile fd; 314 status_t res = fd.open(path->get_native()); 315 if (res != STATUS_OK) 316 { 317 fd.close(); 318 return res; 319 } 320 321 uint32_t chunk_id = 0; 322 323 // Read profile (if present) 324 size_t skip = 0; 325 size_t profVersion = 1; 326 LSPCChunkReader *prof = fd.find_chunk(LSPC_CHUNK_PROFILE); 327 if (prof != NULL) 328 { 329 // Read profile header and check version 330 lspc_chunk_audio_profile_t p; 331 ssize_t n = prof->read_header(&p, sizeof(lspc_chunk_audio_profile_t)); 332 if (n < 0) 333 res = status_t(-n); 334 else if ((p.common.version < 1) || (p.common.size < sizeof(lspc_chunk_audio_profile_t))) 335 res = STATUS_CORRUPTED_FILE; 336 337 // Get related chunk identifier 338 chunk_id = BE_TO_CPU(p.chunk_id); 339 if ((res == STATUS_OK) && (chunk_id == 0)) 340 res = STATUS_CORRUPTED_FILE; 341 342 // Get skip value: 343 profVersion = p.common.version; 344 if (profVersion >= 2) 345 skip = BE_TO_CPU(p.skip); 346 347 // Analyze final status 348 status_t res2 = prof->close(); 349 if (res == STATUS_OK) 350 res = res2; 351 delete prof; 352 353 // Analyze status 354 if (res != STATUS_OK) 355 { 356 fd.close(); 357 return res; 358 } 359 } 360 361 // Try to open audio file chunk 362 LSPCAudioReader ar; 363 res = (chunk_id > 0) ? ar.open(&fd, chunk_id) : ar.open(&fd); 364 if (res != STATUS_OK) 365 { 366 ar.close(); 367 fd.close(); 368 return STATUS_BAD_FORMAT; 369 } 370 371 // Read audio chunk header and check its size 372 lspc_audio_parameters_t aparams; 373 res = ar.get_parameters(&aparams); 374 if (res != STATUS_OK) 375 { 376 ar.close(); 377 fd.close(); 378 return res; 379 } 380 381 // Setting up skip value for version 1 headers 382 if (profVersion < 2) 383 { 384 LSPCChunkReader *rd = fd.read_chunk(ar.unique_id()); // Read the chunk with same ID as audio stream reader found 385 lspc_chunk_audio_header_t hdr; 386 387 ssize_t res = rd->read_header(&hdr, sizeof(lspc_chunk_audio_header_t)); 388 if ((res >= 0) && (hdr.common.version < 2)) // Field 'offset' is deprecated in header since version 2 389 { 390 ssize_t offset = BE_TO_CPU(hdr.offset); 391 392 size_t middle = aparams.frames / 2 - 1; 393 size_t skipNoOffset = middle - 1; 394 size_t maxAhead = aparams.frames - skipNoOffset; 395 396 if (offset >= 0) 397 { 398 size_t nOffset = offset; 399 nOffset = (nOffset > maxAhead)? maxAhead : nOffset; 400 skip = skipNoOffset + nOffset; 401 } 402 else 403 { 404 size_t nOffset = -offset; 405 nOffset = (nOffset > skipNoOffset)? skipNoOffset : nOffset; 406 skip = skipNoOffset - nOffset; 407 } 408 } 409 410 // Close reader and free resource 411 res = rd->close(); 412 if (res != STATUS_OK) 413 { 414 rd->close(); 415 delete rd; 416 ar.close(); 417 fd.close(); 418 return res; 419 } 420 delete rd; 421 rd = NULL; 422 } 423 424 skip = (skip > aparams.frames)? aparams.frames : skip; 425 size_t max_samples = (max_duration >= 0.0f) ? seconds_to_samples(aparams.sample_rate, max_duration) : -1; 426 lsp_trace("file parameters: frames=%d, channels=%d, sample_rate=%d max_duration=%.3f, max_samples=%d", 427 int(aparams.frames), int(aparams.channels), int(aparams.sample_rate), max_duration, int(max_samples)); 428 429 aparams.frames -= skip; // Remove number of frames to skip from audio parameters 430 431 // Patch audio header 432 if ((max_samples >= 0) && (aparams.frames > max_samples)) 433 aparams.frames = max_samples; 434 435 // Skip set of frames 436 if (skip > 0) 437 { 438 ssize_t skipped = ar.skip_frames(skip); 439 if (skipped != ssize_t(skip)) 440 { 441 ar.close(); 442 fd.close(); 443 return (skipped >= 0) ? STATUS_CORRUPTED_FILE : -skipped; 444 } 445 } 446 447 // Create file content 448 file_content_t *fc = NULL; 449 if (res == STATUS_OK) 450 { 451 fc = create_file_content(aparams.channels, aparams.frames); 452 if (fc == NULL) 453 { 454 ar.close(); 455 fd.close(); 456 return STATUS_NO_MEM; 457 } 458 459 fc->nSampleRate = aparams.sample_rate; 460 } 461 462 // Allocate temporary buffer 463 temporary_buffer_t *tb = create_temporary_buffer(fc); 464 if (tb == NULL) 465 { 466 destroy_file_content(fc); 467 ar.close(); 468 fd.close(); 469 return STATUS_NO_MEM; 470 } 471 472 // Read frames 473 skip = aparams.frames; 474 while (skip > 0) 475 { 476 // Determine how many data is available to read 477 size_t can_read = (tb->nCapacity - tb->nSize)/tb->nFrameSize; 478 if (can_read <= 0) 479 { 480 flush_temporary_buffer(tb); 481 can_read = (tb->nCapacity - tb->nSize)/tb->nFrameSize; 482 } 483 484 // Calculate amount of samples to read 485 size_t to_read = (skip > can_read) ? can_read : skip; 486 487 ssize_t n = ar.read_frames(reinterpret_cast<float *>(&tb->bData[tb->nSize]), to_read); 488 if (n < 0) 489 { 490 destroy_temporary_buffer(tb); 491 destroy_file_content(fc); 492 ar.close(); 493 fd.close(); 494 return -n; 495 } 496 497 // Update counters 498 tb->nSize += n * tb->nFrameSize; 499 skip -= n; 500 } 501 502 // Flush last read data (if present) 503 flush_temporary_buffer(tb); 504 505 // Destroy temporary buffer 506 if (tb != NULL) 507 { 508 destroy_temporary_buffer(tb); 509 tb = NULL; 510 } 511 512 // Close chunk reader 513 res = ar.close(); 514 if (res != STATUS_OK) 515 { 516 destroy_file_content(fc); 517 ar.close(); 518 fd.close(); 519 return res; 520 } 521 522 // Close LSPC file 523 res = fd.close(); 524 if (res != STATUS_OK) 525 { 526 destroy_file_content(fc); 527 fd.close(); 528 return res; 529 } 530 531 // Destroy previously used content and store new 532 if (pData != NULL) 533 destroy_file_content(pData); 534 pData = fc; 535 536 return STATUS_OK; 537 } 538 load(const char * path,float max_duration)539 status_t AudioFile::load(const char *path, float max_duration) 540 { 541 if (path == NULL) 542 return STATUS_BAD_ARGUMENTS; 543 544 LSPString spath; 545 if (!spath.set_utf8(path)) 546 return STATUS_NO_MEM; 547 548 return load(&spath, max_duration); 549 } 550 load(const LSPString * path,float max_duration)551 status_t AudioFile::load(const LSPString *path, float max_duration) 552 { 553 if (path == NULL) 554 return STATUS_BAD_ARGUMENTS; 555 556 status_t res = load_lspc(path, max_duration); 557 if (res != STATUS_OK) 558 { 559 #ifdef PLATFORM_WINDOWS 560 // res = load_mfapi(path, max_duration); 561 // if (res == STATUS_BAD_FORMAT) 562 res = load_mmio(path, max_duration); 563 #else 564 res = load_sndfile(path, max_duration); 565 #endif /* PLATFORM_WINDOWS */ 566 } 567 return res; 568 } 569 store_samples(const LSPString * path,size_t from,size_t max_count)570 status_t AudioFile::store_samples(const LSPString *path, size_t from, size_t max_count) 571 { 572 if (pData == NULL) 573 return STATUS_NO_DATA; 574 575 #ifdef PLATFORM_WINDOWS 576 status_t res = save_mfapi(path, from, max_count); 577 if (res == STATUS_BAD_FORMAT) 578 res = save_mmio(path, from, max_count); 579 #else 580 status_t res = save_sndfile(path, from, max_count); 581 #endif 582 583 return res; 584 } 585 load(const io::Path * path,float max_duration)586 status_t AudioFile::load(const io::Path *path, float max_duration) 587 { 588 if (path == NULL) 589 return STATUS_BAD_ARGUMENTS; 590 return load(path->as_string(), max_duration); 591 } 592 store_samples(const io::Path * path,size_t from,size_t max_count)593 status_t AudioFile::store_samples(const io::Path *path, size_t from, size_t max_count) { 594 if (path == NULL) 595 return STATUS_BAD_ARGUMENTS; 596 return store_samples(path->as_string(), from, max_count); 597 } 598 store_samples(const char * path,size_t from,size_t max_count)599 status_t AudioFile::store_samples(const char *path, size_t from, size_t max_count) 600 { 601 if (path == NULL) 602 return STATUS_BAD_ARGUMENTS; 603 LSPString spath; 604 if (!spath.set_utf8(path)) 605 return STATUS_NO_MEM; 606 return store_samples(&spath, from, max_count); 607 } 608 store_samples(const char * path,size_t max_count)609 status_t AudioFile::store_samples(const char *path, size_t max_count) 610 { 611 if (path == NULL) 612 return STATUS_BAD_ARGUMENTS; 613 LSPString spath; 614 if (!spath.set_utf8(path)) 615 return STATUS_NO_MEM; 616 return store_samples(&spath, 0, max_count); 617 } 618 store_samples(const LSPString * path,size_t max_count)619 status_t AudioFile::store_samples(const LSPString *path, size_t max_count) 620 { 621 return store_samples(path, 0, max_count); 622 } 623 store_samples(const io::Path * path,size_t max_count)624 status_t AudioFile::store_samples(const io::Path *path, size_t max_count) 625 { 626 if (path == NULL) 627 return STATUS_BAD_ARGUMENTS; 628 return store_samples(path->as_string(), 0, max_count); 629 } 630 store(const char * path,float max_duration)631 status_t AudioFile::store(const char *path, float max_duration) 632 { 633 if (path == NULL) 634 return STATUS_BAD_ARGUMENTS; 635 636 // Calculate the file length (in samples) and call the previous method 637 size_t max_count = (max_duration < 0) ? pData->nSamples : max_duration * pData->nSampleRate; 638 LSPString spath; 639 if (!spath.set_utf8(path)) 640 return STATUS_NO_MEM; 641 642 return store_samples(&spath, 0, max_count); 643 } 644 store(const LSPString * path,float max_duration)645 status_t AudioFile::store(const LSPString *path, float max_duration) 646 { 647 if (path == NULL) 648 return STATUS_BAD_ARGUMENTS; 649 650 // Calculate the file length (in samples) and call the previous method 651 size_t max_count = (max_duration < 0) ? pData->nSamples : max_duration * pData->nSampleRate; 652 return store_samples(path, 0, max_count); 653 } 654 store(const io::Path * path,float max_duration)655 status_t AudioFile::store(const io::Path *path, float max_duration) 656 { 657 if (path == NULL) 658 return STATUS_BAD_ARGUMENTS; 659 660 // Calculate the file length (in samples) and call the previous method 661 size_t max_count = (max_duration < 0) ? pData->nSamples : max_duration * pData->nSampleRate; 662 return store_samples(path->as_string(), 0, max_count); 663 } 664 reverse(ssize_t track_id)665 bool AudioFile::reverse(ssize_t track_id) 666 { 667 if (pData == NULL) 668 return false; 669 670 if (track_id >= 0) 671 { 672 if (size_t(track_id) >= pData->nChannels) 673 return false; 674 lsp_trace("reverse %p, %d", pData->vChannels[track_id], int(pData->nSamples)); 675 dsp::reverse1(pData->vChannels[track_id], pData->nSamples); 676 } 677 else 678 { 679 size_t count = pData->nChannels; 680 if (count <= 0) 681 return false; 682 for (size_t i=0; i<count; ++i) 683 { 684 lsp_trace("reverse %p, %d", pData->vChannels[i], int(pData->nSamples)); 685 dsp::reverse1(pData->vChannels[i], pData->nSamples); 686 } 687 } 688 689 return true; 690 } 691 channels() const692 size_t AudioFile::channels() const 693 { 694 return (pData != NULL) ? pData->nChannels : 0; 695 } 696 samples() const697 size_t AudioFile::samples() const 698 { 699 return (pData != NULL) ? pData->nSamples : 0; 700 } 701 sample_rate() const702 size_t AudioFile::sample_rate() const 703 { 704 return (pData != NULL) ? pData->nSampleRate : 0; 705 } 706 resample(size_t new_sample_rate)707 status_t AudioFile::resample(size_t new_sample_rate) 708 { 709 // Check that resampling is actually needed 710 if (new_sample_rate > pData->nSampleRate) 711 { 712 // Need to up-sample data 713 if ((new_sample_rate % pData->nSampleRate) == 0) 714 return fast_upsample(new_sample_rate); 715 else 716 return complex_upsample(new_sample_rate); 717 } 718 else if (new_sample_rate < pData->nSampleRate) 719 { 720 // Need to down-sample data 721 if ((pData->nSampleRate % new_sample_rate) == 0) 722 return fast_downsample(new_sample_rate); 723 else 724 return complex_downsample(new_sample_rate); 725 } 726 727 // Return OK status 728 return STATUS_OK; 729 } 730 fast_downsample(size_t new_sample_rate)731 status_t AudioFile::fast_downsample(size_t new_sample_rate) 732 { 733 size_t rkf = pData->nSampleRate / new_sample_rate; 734 size_t new_samples = pData->nSamples / rkf; 735 736 // Prepare new data structure to store resampled data 737 file_content_t *fc = create_file_content(pData->nChannels, new_samples); 738 if (fc == NULL) 739 return STATUS_NO_MEM; 740 fc->nSampleRate = new_sample_rate; 741 742 // Iterate each channel 743 for (size_t c=0; c<fc->nChannels; ++c) 744 { 745 const float *src = pData->vChannels[c]; 746 float *dst = fc->vChannels[c]; 747 748 for (size_t i=0, p=0; i < pData->nSamples; i += rkf, p++) 749 dst[p] = src[i]; 750 } 751 752 // Destroy old data content 753 destroy_file_content(pData); 754 755 // Store new file content 756 pData = fc; 757 758 return STATUS_OK; 759 } 760 fast_upsample(size_t new_sample_rate)761 status_t AudioFile::fast_upsample(size_t new_sample_rate) 762 { 763 // Calculate parameters of transformation 764 ssize_t kf = new_sample_rate / pData->nSampleRate; 765 float rkf = 1.0f / kf; 766 767 // Prepare kernel for resampling 768 ssize_t k_periods = RESAMPLING_PERIODS; // * (kf >> 1); 769 ssize_t k_base = k_periods * kf; 770 ssize_t k_center = k_base + 1; 771 ssize_t k_len = (k_center << 1) + 1; 772 ssize_t k_size = ALIGN_SIZE(k_len + 1, 4); // Additional sample for time offset 773 float *k = lsp_tmalloc(float, k_size); 774 if (k == NULL) 775 return STATUS_NO_MEM; 776 777 // Prepare temporary buffer for resampling 778 size_t new_samples = kf * pData->nSamples; 779 size_t b_len = new_samples + k_size; 780 size_t b_size = ALIGN_SIZE(b_len, 4); 781 float *b = lsp_tmalloc(float, b_size); 782 if (b == NULL) 783 { 784 lsp_free(k); 785 return STATUS_NO_MEM; 786 } 787 788 // Prepare new data structure to store resampled data 789 file_content_t *fc = create_file_content(pData->nChannels, new_samples); 790 if (fc == NULL) 791 { 792 lsp_free(b); 793 lsp_free(k); 794 return STATUS_NO_MEM; 795 } 796 fc->nSampleRate = new_sample_rate; 797 798 // Generate Lanczos kernel 799 for (ssize_t j=0; j<k_size; ++j) 800 { 801 float t = (j - k_center) * rkf; 802 803 if ((t > -k_periods) && (t < k_periods)) 804 { 805 if (t != 0) 806 { 807 float t2 = M_PI * t; 808 k[j] = k_periods * sinf(t2) * sinf(t2 / k_periods) / (t2 * t2); 809 } 810 else 811 k[j] = 1.0f; 812 } 813 else 814 k[j] = 0.0f; 815 } 816 817 // Output dump 818 // printf("----------------------\n"); 819 // printf("j;t;k(j);\n"); 820 // for (ssize_t j=0; j<k_len; ++j) 821 // { 822 // float t = (j - k_center) * rkf; 823 // printf("%d;%f;%f;\n", int(j), t, k[j]); 824 // } 825 // printf("----------------------\n"); 826 827 // Iterate each channel 828 for (size_t c=0; c<fc->nChannels; ++c) 829 { 830 const float *src = pData->vChannels[c]; 831 dsp::fill_zero(b, b_size); // Clear the temporary buffer 832 833 // Perform convolutions 834 for (size_t i=0, p=0; i<pData->nSamples; i++, p += kf) 835 dsp::fmadd_k3(&b[p], k, src[i], k_size); 836 837 // Copy the data to the file content 838 dsp::copy(fc->vChannels[c], &b[k_center], fc->nSamples); 839 } 840 841 // Delete temporary buffers 842 destroy_file_content(pData); 843 lsp_free(b); 844 lsp_free(k); 845 846 // Store new file content 847 pData = fc; 848 849 return STATUS_OK; 850 } 851 complex_upsample(size_t new_sample_rate)852 status_t AudioFile::complex_upsample(size_t new_sample_rate) 853 { 854 // Calculate parameters of transformation 855 ssize_t gcd = gcd_euclid(new_sample_rate, pData->nSampleRate); 856 ssize_t src_step = pData->nSampleRate / gcd; 857 ssize_t dst_step = new_sample_rate / gcd; 858 float kf = float(dst_step) / float(src_step); 859 float rkf = float(src_step) / float(dst_step); 860 861 // Prepare kernel for resampling 862 ssize_t k_periods = RESAMPLING_PERIODS; // Number of periods 863 ssize_t k_base = k_periods * kf; 864 ssize_t k_center = k_base + 1; 865 ssize_t k_len = (k_center << 1) + 1; // Centered impulse response 866 ssize_t k_size = ALIGN_SIZE(k_len + 1, 4); // Additional sample for time offset 867 float *k = lsp_tmalloc(float, k_size); 868 if (k == NULL) 869 return STATUS_NO_MEM; 870 871 // Prepare temporary buffer for resampling 872 size_t new_samples = kf * pData->nSamples; 873 size_t b_len = new_samples + k_size; 874 size_t b_size = ALIGN_SIZE(b_len, 4); 875 float *b = lsp_tmalloc(float, b_size); 876 if (b == NULL) 877 { 878 lsp_free(k); 879 return STATUS_NO_MEM; 880 } 881 882 // Prepare new data structure to store resampled data 883 file_content_t *fc = create_file_content(pData->nChannels, new_samples); 884 if (fc == NULL) 885 { 886 lsp_free(b); 887 lsp_free(k); 888 return STATUS_NO_MEM; 889 } 890 fc->nSampleRate = new_sample_rate; 891 892 // Iterate each channel 893 for (size_t c=0; c<fc->nChannels; ++c) 894 { 895 const float *src = pData->vChannels[c]; 896 dsp::fill_zero(b, b_size); // Clear the temporary buffer 897 898 for (ssize_t i=0; i<src_step; ++i) 899 { 900 // calculate the offset between nearest samples 901 ssize_t p = kf * i; 902 float dt = i*kf - p; 903 904 // Generate Lanczos kernel 905 for (ssize_t j=0; j<k_size; ++j) 906 { 907 float t = (j - k_center - dt) * rkf; 908 909 if ((t > -k_periods) && (t < k_periods)) 910 { 911 if (t != 0.0f) 912 { 913 float t2 = M_PI * t; 914 k[j] = k_periods * sinf(t2) * sinf(t2 / k_periods) / (t2 * t2); 915 } 916 else 917 k[j] = 1.0f; 918 } 919 else 920 k[j] = 0.0f; 921 } 922 923 // Output dump 924 // printf("----------------------\n"); 925 // printf("j;t;k(j);\n"); 926 // for (ssize_t j=0; j<k_len; ++j) 927 // { 928 // float t = (j - k_center - dt) * kt; 929 // printf("%d;%f;%f;\n", int(j), t, k[j]); 930 // } 931 // printf("----------------------\n"); 932 933 // Perform convolutions 934 for (size_t j=i; j<pData->nSamples; j += src_step) 935 { 936 dsp::fmadd_k3(&b[p], k, src[j], k_size); 937 p += dst_step; 938 } 939 } 940 941 // Copy the data to the file content 942 dsp::copy(fc->vChannels[c], &b[k_center], fc->nSamples); 943 } 944 945 // Delete temporary buffers 946 destroy_file_content(pData); 947 lsp_free(b); 948 lsp_free(k); 949 950 // Store new file content 951 pData = fc; 952 953 return STATUS_OK; 954 } 955 complex_downsample(size_t new_sample_rate)956 status_t AudioFile::complex_downsample(size_t new_sample_rate) 957 { 958 // Calculate parameters of transformation 959 ssize_t gcd = gcd_euclid(new_sample_rate, pData->nSampleRate); 960 ssize_t src_step = pData->nSampleRate / gcd; 961 ssize_t dst_step = new_sample_rate / gcd; 962 float kf = float(dst_step) / float(src_step); 963 float rkf = float(src_step) / float(dst_step); 964 965 // Prepare kernel for resampling 966 ssize_t k_base = RESAMPLING_PERIODS; 967 ssize_t k_periods = k_base * rkf; // Number of periods 968 ssize_t k_center = k_base + 1; 969 ssize_t k_len = (k_center << 1) + rkf + 1; // Centered impulse response 970 ssize_t k_size = ALIGN_SIZE(k_len + 1, 4); // Additional sample for time offset 971 float *k = lsp_tmalloc(float, k_size); 972 if (k == NULL) 973 return STATUS_NO_MEM; 974 975 // Prepare temporary buffer for resampling 976 size_t new_samples = kf * pData->nSamples; 977 size_t b_len = new_samples + k_size; 978 size_t b_size = ALIGN_SIZE(b_len, 4); 979 float *b = lsp_tmalloc(float, b_size); 980 if (b == NULL) 981 { 982 lsp_free(k); 983 return STATUS_NO_MEM; 984 } 985 986 // Prepare new data structure to store resampled data 987 file_content_t *fc = create_file_content(pData->nChannels, new_samples); 988 if (fc == NULL) 989 { 990 lsp_free(b); 991 lsp_free(k); 992 return STATUS_NO_MEM; 993 } 994 fc->nSampleRate = new_sample_rate; 995 996 // Iterate each channel 997 for (size_t c=0; c<fc->nChannels; ++c) 998 { 999 const float *src = pData->vChannels[c]; 1000 dsp::fill_zero(b, b_size); // Clear the temporary buffer 1001 1002 for (ssize_t i=0; i<src_step; ++i) 1003 { 1004 // calculate the offset between nearest samples 1005 ssize_t p = kf * i; 1006 float dt = i*kf - p; // Always positive, in range of [0..1] 1007 1008 // Generate Lanczos kernel 1009 for (ssize_t j=0; j<k_size; ++j) 1010 { 1011 float t = (j - k_center - dt) * rkf; 1012 1013 if ((t > -k_periods) && (t < k_periods)) 1014 { 1015 if (t != 0.0f) 1016 { 1017 float t2 = M_PI * t; 1018 k[j] = k_periods * sinf(t2) * sinf(t2 / k_periods) / (t2 * t2); 1019 } 1020 else 1021 k[j] = 1.0f; 1022 } 1023 else 1024 k[j] = 0.0f; 1025 } 1026 1027 // Output dump 1028 // printf("----------------------\n"); 1029 // printf("j;t;k(j);\n"); 1030 // for (ssize_t j=0; j<k_size; ++j) 1031 // { 1032 // float t = (j - k_center - dt) * kt; 1033 // printf("%d;%f;%f;\n", int(j), t, k[j]); 1034 // } 1035 // printf("----------------------\n"); 1036 1037 // Perform convolutions 1038 for (size_t j=i; j<pData->nSamples; j += src_step) 1039 { 1040 dsp::fmadd_k3(&b[p], k, src[j], k_size); 1041 p += dst_step; 1042 } 1043 } 1044 1045 // Copy the data to the file content 1046 dsp::copy(fc->vChannels[c], &b[k_center], fc->nSamples); 1047 } 1048 1049 // Delete temporary buffers 1050 destroy_file_content(pData); 1051 lsp_free(b); 1052 lsp_free(k); 1053 1054 // Store new file content 1055 pData = fc; 1056 1057 return STATUS_OK; 1058 } 1059 channel(size_t track)1060 float *AudioFile::channel(size_t track) 1061 { 1062 if (pData == NULL) 1063 return NULL; 1064 if (track >= pData->nChannels) 1065 return NULL; 1066 return pData->vChannels[track]; 1067 } 1068 convert_to_sample(Sample * dst)1069 status_t AudioFile::convert_to_sample(Sample *dst) 1070 { 1071 if (dst == NULL) 1072 return STATUS_BAD_ARGUMENTS; 1073 if (pData == NULL) 1074 return STATUS_BAD_STATE; 1075 1076 // Create and initialize temorary sample instance 1077 Sample tmp; 1078 if (!tmp.init(pData->nChannels, pData->nSamples, pData->nSamples)) 1079 return STATUS_NO_MEM; 1080 1081 // Copy file contents to sample 1082 for (size_t i=0; i<pData->nChannels; ++i) 1083 dsp::copy(tmp.getBuffer(i), pData->vChannels[i], pData->nSamples); 1084 1085 tmp.swap(dst); 1086 tmp.destroy(); 1087 return STATUS_OK; 1088 } 1089 1090 #ifdef PLATFORM_WINDOWS 1091 typedef struct stream_info_t 1092 { 1093 UINT64 frames; // Number of frames 1094 UINT32 srate; // Sample rate 1095 UINT32 channels; // Number of channels 1096 DWORD stream; // Identifier of the stream 1097 } stream_info_t; 1098 create_riff_file(const WCHAR * path,WAVEFORMATEX * pwfxDest,HMMIO * phmmioOut,MMCKINFO * pckOut,MMCKINFO * pckOutRIFF)1099 status_t create_riff_file( 1100 const WCHAR *path, 1101 WAVEFORMATEX *pwfxDest, 1102 HMMIO *phmmioOut, 1103 MMCKINFO *pckOut, 1104 MMCKINFO *pckOutRIFF 1105 ) 1106 { 1107 int code; 1108 size_t written; 1109 MMCKINFO ckOut1; 1110 DWORD dwFactChunk = DWORD(-1); 1111 1112 HMMIO fd = ::mmioOpenW(const_cast<WCHAR *>(path), NULL, MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_CREATE); 1113 if (fd == NULL) 1114 return STATUS_IO_ERROR; 1115 1116 // Create the output file RIFF chunk of form type 'WAVE' 1117 pckOutRIFF->fccType = mmioFOURCC('W', 'A', 'V', 'E'); 1118 pckOutRIFF->cksize = 0; 1119 if ((code = ::mmioCreateChunk(fd, pckOutRIFF, MMIO_CREATERIFF)) != 0) 1120 { 1121 ::mmioClose(fd, 0); 1122 return STATUS_IO_ERROR; 1123 } 1124 1125 // Now create the 'fmt ' chunk. Since we know the size of this chunk, 1126 pckOut->ckid = mmioFOURCC('f', 'm', 't', ' '); 1127 pckOut->cksize = sizeof(PCMWAVEFORMAT); // we know the size of this ck. 1128 if ((code = mmioCreateChunk(fd, pckOut, 0)) != 0) 1129 { 1130 ::mmioClose(fd, 0); 1131 return STATUS_IO_ERROR; 1132 } 1133 1134 // Write the PCMWAVEFORMAT structure to the 'fmt ' chunk 1135 written = ::mmioWrite(fd, reinterpret_cast<HPSTR>(pwfxDest), sizeof(PCMWAVEFORMAT)); 1136 if (written != sizeof(PCMWAVEFORMAT)) 1137 { 1138 ::mmioClose(fd, 0); 1139 return STATUS_IO_ERROR; 1140 } 1141 1142 // Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk. 1143 if ((code = ::mmioAscend(fd, pckOut, 0)) != 0) 1144 { 1145 ::mmioClose(fd, 0); 1146 return STATUS_IO_ERROR; 1147 } 1148 1149 // Now create the fact chunk, not required for PCM but nice to have. 1150 ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); 1151 ckOut1.cksize = 0; 1152 if ((code = ::mmioCreateChunk(fd, &ckOut1, 0)) != 0) 1153 { 1154 ::mmioClose(fd, 0); 1155 return STATUS_IO_ERROR; 1156 } 1157 1158 written = ::mmioWrite(fd, reinterpret_cast<HPSTR>(&dwFactChunk), sizeof(dwFactChunk)); 1159 if (written != sizeof(dwFactChunk)) 1160 { 1161 ::mmioClose(fd, 0); 1162 return STATUS_IO_ERROR; 1163 } 1164 1165 // Now ascend out of the fact chunk... 1166 if ((code = ::mmioAscend(fd, &ckOut1, 0)) != 0) 1167 { 1168 ::mmioClose(fd, 0); 1169 return STATUS_IO_ERROR; 1170 } 1171 1172 // Save pointer and return success status 1173 *phmmioOut = fd; 1174 return STATUS_OK; 1175 } 1176 open_riff_file(const WCHAR * path,HMMIO * phmmioIn,WAVEFORMATEX ** ppwfxInfo,MMCKINFO * pckInRIFF)1177 status_t open_riff_file( 1178 const WCHAR *path, 1179 HMMIO *phmmioIn, 1180 WAVEFORMATEX **ppwfxInfo, 1181 MMCKINFO *pckInRIFF 1182 ) 1183 { 1184 HMMIO hmmioIn; 1185 MMCKINFO ckIn; 1186 PCMWAVEFORMAT pcmWaveFormat; 1187 int error; 1188 1189 if ((hmmioIn = ::mmioOpenW(const_cast<WCHAR *>(path), NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL) 1190 return STATUS_PERMISSION_DENIED; 1191 1192 if ((error = int(::mmioDescend(hmmioIn, pckInRIFF, NULL, 0))) != 0) 1193 { 1194 ::mmioClose(hmmioIn, 0); 1195 return STATUS_BAD_FORMAT; 1196 } 1197 1198 if ((pckInRIFF->ckid != FOURCC_RIFF) || (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E'))) 1199 { 1200 ::mmioClose(hmmioIn, 0); 1201 return STATUS_BAD_FORMAT; 1202 } 1203 1204 ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); 1205 if ((error = int(::mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK))) != 0) 1206 { 1207 ::mmioClose(hmmioIn, 0); 1208 return STATUS_BAD_FORMAT; 1209 } 1210 1211 // Expect the 'fmt' chunk to be at least as large as sizeof(PCMWAVEFORMAT) 1212 if (ckIn.cksize < sizeof(PCMWAVEFORMAT)) 1213 { 1214 ::mmioClose(hmmioIn, 0); 1215 return STATUS_BAD_FORMAT; 1216 } 1217 1218 // Read the 'fmt ' chunk 1219 size_t bytes = ::mmioRead(hmmioIn, (HPSTR) &pcmWaveFormat, sizeof(PCMWAVEFORMAT)); 1220 if (bytes != sizeof(PCMWAVEFORMAT)) 1221 { 1222 ::mmioClose(hmmioIn, 0); 1223 return STATUS_BAD_FORMAT; 1224 } 1225 1226 // Estimate number of bytes to allocate for the format descriptor 1227 WAVEFORMATEX *wfex = NULL; 1228 1229 if (LE_TO_CPU(pcmWaveFormat.wf.wFormatTag) != WAVE_FORMAT_PCM) 1230 { 1231 WORD cbSize; 1232 size_t alloc = sizeof(WAVEFORMATEX); 1233 1234 // Read in length of extra bytes. 1235 bytes = ::mmioRead(hmmioIn, reinterpret_cast<HPSTR>(&cbSize), sizeof(WORD)); 1236 if (bytes != sizeof(WORD)) 1237 { 1238 ::mmioClose(hmmioIn, 0); 1239 return STATUS_BAD_FORMAT; 1240 } 1241 alloc += LE_TO_CPU(cbSize); 1242 1243 // Allocate memory 1244 wfex = reinterpret_cast<WAVEFORMATEX *>(::malloc(alloc)); 1245 if (wfex == NULL) 1246 { 1247 ::mmioClose(hmmioIn, 0); 1248 return STATUS_BAD_FORMAT; 1249 } 1250 1251 // Return back to 'fmt ' chunk 1252 if ((error = int(::mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK))) != 0) 1253 { 1254 ::mmioClose(hmmioIn, 0); 1255 return STATUS_BAD_FORMAT; 1256 } 1257 1258 // Read the whole structure again 1259 bytes = ::mmioRead(hmmioIn, reinterpret_cast<HPSTR>(wfex), alloc); 1260 if (bytes != alloc) 1261 { 1262 ::mmioClose(hmmioIn, 0); 1263 return STATUS_BAD_FORMAT; 1264 } 1265 } 1266 else 1267 { 1268 // Allocate memory 1269 wfex = reinterpret_cast<WAVEFORMATEX *>(::malloc(sizeof(WAVEFORMATEX))); 1270 if (wfex == NULL) 1271 { 1272 ::mmioClose(hmmioIn, 0); 1273 return STATUS_BAD_FORMAT; 1274 } 1275 ::memcpy(wfex, &pcmWaveFormat, sizeof(PCMWAVEFORMAT)); 1276 wfex->cbSize = 0; 1277 } 1278 1279 /* Ascend the input file out of the 'fmt ' chunk. */ 1280 if ((error = ::mmioAscend(hmmioIn, &ckIn, 0)) != 0) 1281 { 1282 ::mmioClose(hmmioIn, 0); 1283 return STATUS_BAD_FORMAT; 1284 } 1285 1286 // Return success result 1287 *phmmioIn = hmmioIn; 1288 *ppwfxInfo = wfex; 1289 1290 return STATUS_OK; 1291 } 1292 complete_riff_file(HMMIO * phmmioOut,MMCKINFO * pckOut,MMCKINFO * pckOutRIFF,MMIOINFO * pmmioinfoOut,size_t samples)1293 status_t complete_riff_file( 1294 HMMIO *phmmioOut, 1295 MMCKINFO *pckOut, 1296 MMCKINFO *pckOutRIFF, 1297 MMIOINFO *pmmioinfoOut, 1298 size_t samples 1299 ) 1300 { 1301 int code; 1302 1303 // Ascend the output file out of the 'data' chunk 1304 // this will cause the chunk size of the 'data' chunk to be written. 1305 if ((code = ::mmioAscend(*phmmioOut, pckOut, 0)) != 0) 1306 { 1307 ::mmioClose(*phmmioOut, 0); 1308 return STATUS_IO_ERROR; 1309 } 1310 1311 // Do this here instead... 1312 if ((code = ::mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) 1313 { 1314 ::mmioClose(*phmmioOut, 0); 1315 return STATUS_IO_ERROR; 1316 } 1317 1318 // Seek to the beginning of the file 1319 code = ::mmioSeek(*phmmioOut, 0, SEEK_SET); 1320 if ((code = int(::mmioDescend(*phmmioOut, pckOutRIFF, NULL, 0))) != 0) 1321 { 1322 ::mmioClose(*phmmioOut, 0); 1323 return STATUS_IO_ERROR; 1324 } 1325 1326 // Update fact 1327 pckOut->ckid = mmioFOURCC('f', 'a', 'c', 't'); 1328 if ((code = ::mmioDescend(*phmmioOut, pckOut, pckOutRIFF, MMIO_FINDCHUNK)) == 0) 1329 { 1330 DWORD cSamples = CPU_TO_LE(DWORD(samples)); 1331 ::mmioWrite(*phmmioOut, reinterpret_cast<HPSTR>(&cSamples), sizeof(DWORD)); 1332 ::mmioAscend(*phmmioOut, pckOut, 0); 1333 } 1334 1335 if ((code = ::mmioAscend(*phmmioOut, pckOutRIFF, 0)) != 0) 1336 { 1337 ::mmioClose(*phmmioOut, 0); 1338 return STATUS_IO_ERROR; 1339 } 1340 1341 // Close MMIO and return 1342 ::mmioClose(*phmmioOut, 0); 1343 return STATUS_OK; 1344 } 1345 mfapi_copy_media_type(IMFMediaType * src,stream_info_t * cfg)1346 static IMFMediaType *mfapi_copy_media_type(IMFMediaType *src, stream_info_t *cfg) 1347 { 1348 // Obtain media type 1349 HRESULT hr = src->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &cfg->srate); 1350 if (SUCCEEDED(hr)) 1351 hr = src->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &cfg->channels); 1352 if (!SUCCEEDED(hr)) 1353 return NULL; 1354 1355 // Create target media type 1356 IMFMediaType *dst = NULL; 1357 hr = ::MFCreateMediaType(&dst); 1358 if (!SUCCEEDED(hr)) 1359 return NULL; 1360 1361 // Configure and set media type for reader 1362 hr = dst->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); 1363 if (SUCCEEDED(hr)) 1364 hr = dst->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float); 1365 if (SUCCEEDED(hr)) 1366 hr = dst->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, sizeof(float) * 8); 1367 if (SUCCEEDED(hr)) 1368 hr = dst->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, cfg->srate); 1369 if (SUCCEEDED(hr)) 1370 hr = dst->SetUINT32(MF_MT_FRAME_SIZE, cfg->channels); 1371 1372 // Check the final result 1373 if (SUCCEEDED(hr)) 1374 return dst; 1375 1376 // Return error 1377 dst->Release(); 1378 return NULL; 1379 } 1380 open_mfapi_reader(const WCHAR * path,stream_info_t * info,IMFSourceReader ** reader)1381 status_t open_mfapi_reader(const WCHAR *path, stream_info_t *info, IMFSourceReader **reader) 1382 { 1383 // Create source reader 1384 IMFSourceReader *pReader = NULL; 1385 HRESULT hr = ::MFCreateSourceReaderFromURL(path, NULL, &pReader); 1386 if ((!SUCCEEDED(hr)) || (pReader == NULL)) 1387 return STATUS_UNKNOWN_ERR; 1388 1389 // Obtain the length of stream in nanoseconds 1390 INT64 nsDuration; 1391 PROPVARIANT var; 1392 hr = pReader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, 1393 MF_PD_DURATION, &var); 1394 if (SUCCEEDED(hr)) 1395 { 1396 hr = ::PropVariantToInt64(var, &nsDuration); 1397 ::PropVariantClear(&var); 1398 } 1399 1400 if (!SUCCEEDED(hr)) 1401 { 1402 pReader->Release(); 1403 return STATUS_UNKNOWN_ERR; 1404 } 1405 1406 // Find the audio stream 1407 IMFMediaType *pNativeType = NULL; 1408 DWORD dwStreamIndex = 0; 1409 1410 while (true) 1411 { 1412 hr = pReader->GetNativeMediaType(dwStreamIndex, 0, &pNativeType); 1413 if (hr == MF_E_NO_MORE_TYPES) 1414 { 1415 pReader->Release(); 1416 return STATUS_BAD_FORMAT; 1417 } 1418 else if (SUCCEEDED(hr)) 1419 { 1420 GUID guid; 1421 hr = pNativeType->GetGUID(MF_MT_MAJOR_TYPE, &guid); 1422 if ((SUCCEEDED(hr)) && (::IsEqualGUID(guid, MFMediaType_Audio))) 1423 break; 1424 pNativeType->Release(); 1425 } 1426 ++dwStreamIndex; 1427 } 1428 1429 // Create media type for decoding 1430 IMFMediaType *pMediaType = mfapi_copy_media_type(pNativeType, info); 1431 pNativeType->Release(); 1432 if (pMediaType == NULL) 1433 { 1434 pReader->Release(); 1435 return STATUS_UNKNOWN_ERR; 1436 } 1437 1438 // Set current media type for decoding 1439 hr = pReader->SetCurrentMediaType(dwStreamIndex, NULL, pMediaType); 1440 pMediaType->Release(); 1441 1442 if (!SUCCEEDED(hr)) 1443 { 1444 pReader->Release(); 1445 return STATUS_UNKNOWN_ERR; 1446 } 1447 1448 // Return success status 1449 info->frames = (nsDuration * info->srate) / 10000000; 1450 info->stream = dwStreamIndex; 1451 *reader = pReader; 1452 return STATUS_OK; 1453 } 1454 load_mfapi(const LSPString * path,float max_duration)1455 status_t AudioFile::load_mfapi(const LSPString *path, float max_duration) 1456 { 1457 stream_info_t sf_info; 1458 IMFSourceReader *pReader = NULL; 1459 1460 // Open sound file 1461 lsp_trace("loading file: %s\n", path->get_native()); 1462 status_t res = open_mfapi_reader(path->get_utf16(), &sf_info, &pReader); 1463 if (res != STATUS_OK) 1464 return res; 1465 1466 // Read sample file 1467 ssize_t max_samples = (max_duration >= 0.0f) ? seconds_to_samples(sf_info.srate, max_duration) : -1; 1468 lsp_trace("file parameters: frames=%d, channels=%d, sample_rate=%d max_duration=%.3f\n, max_samples=%d", 1469 int(sf_info.frames), int(sf_info.channels), int(sf_info.srate), max_duration, int(max_samples)); 1470 1471 // Patch sf_info 1472 if ((max_samples >= 0) && (sf_info.frames > UINT64(max_samples))) 1473 sf_info.frames = max_samples; 1474 1475 // Create file content 1476 file_content_t *fc = create_file_content(sf_info.channels, sf_info.frames); 1477 if (fc == NULL) 1478 { 1479 pReader->Release(); 1480 return STATUS_NO_MEM; 1481 } 1482 fc->nSampleRate = sf_info.srate; 1483 1484 // Allocate temporary buffer 1485 temporary_buffer_t *tb = create_temporary_buffer(fc); 1486 if (tb == NULL) 1487 { 1488 destroy_file_content(fc); 1489 pReader->Release(); 1490 return STATUS_NO_MEM; 1491 } 1492 1493 size_t count = sf_info.frames; 1494 while (count > 0) 1495 { 1496 // Read sample 1497 IMFSample *pSample = NULL; 1498 DWORD streamIndex, flags; 1499 LONGLONG llTimeStamp; 1500 1501 HRESULT hr = pReader->ReadSample( 1502 sf_info.stream, // Stream index. 1503 0, // Flags. 1504 &streamIndex, // Receives the actual stream index. 1505 &flags, // Receives status flags. 1506 &llTimeStamp, // Receives the time stamp. 1507 &pSample // Receives the sample or NULL. 1508 ); 1509 1510 if (!SUCCEEDED(hr)) 1511 { 1512 destroy_temporary_buffer(tb); 1513 destroy_file_content(fc); 1514 pReader->Release(); 1515 return STATUS_CORRUPTED_FILE; 1516 } 1517 1518 // Obtain number of buffers 1519 DWORD cBuffers = 0; 1520 hr = pSample->GetBufferCount(&cBuffers); 1521 if (!SUCCEEDED(hr)) 1522 { 1523 destroy_temporary_buffer(tb); 1524 destroy_file_content(fc); 1525 pSample->Release(); 1526 pReader->Release(); 1527 return STATUS_CORRUPTED_FILE; 1528 } 1529 1530 // Iterate each buffer 1531 for (DWORD i = 0; (i < cBuffers) && (count > 0); i++) 1532 { 1533 IMFMediaBuffer *pBuffer = NULL; 1534 hr = pSample->GetBufferByIndex(i, &pBuffer); 1535 if (!SUCCEEDED(hr)) 1536 { 1537 destroy_temporary_buffer(tb); 1538 destroy_file_content(fc); 1539 pSample->Release(); 1540 pReader->Release(); 1541 return STATUS_CORRUPTED_FILE; 1542 } 1543 1544 // Use buffer 1545 BYTE *pData = NULL; 1546 DWORD nBufLength = 0; 1547 hr = pBuffer->Lock(&pData, NULL, &nBufLength); 1548 if (!SUCCEEDED(hr)) 1549 { 1550 destroy_temporary_buffer(tb); 1551 destroy_file_content(fc); 1552 pSample->Release(); 1553 pReader->Release(); 1554 return STATUS_CORRUPTED_FILE; 1555 } 1556 1557 while ((count > 0) && (nBufLength > 0)) 1558 { 1559 // Determine how many data is available to read 1560 size_t can_read = tb->nCapacity - tb->nSize; 1561 if (can_read <= 0) 1562 { 1563 flush_temporary_buffer(tb); 1564 can_read = tb->nCapacity - tb->nSize; 1565 } 1566 if (can_read > nBufLength) 1567 can_read = nBufLength; 1568 ::memcpy(&tb->bData[tb->nSize], pData, can_read); 1569 pData += can_read; 1570 tb->nSize += can_read; 1571 nBufLength -= can_read; 1572 } 1573 1574 // Release buffer 1575 pBuffer->Unlock(); 1576 pBuffer->Release(); 1577 } 1578 1579 // Release sample 1580 pSample->Release(); 1581 } 1582 1583 // Flush last read data (if present) 1584 flush_temporary_buffer(tb); 1585 1586 // Free allocated resources 1587 destroy_temporary_buffer(tb); 1588 pReader->Release(); 1589 1590 // Destroy previously used content and store new 1591 if (pData != NULL) 1592 destroy_file_content(pData); 1593 pData = fc; 1594 1595 return STATUS_OK; 1596 } 1597 1598 mfapi_create_sample(void * data,size_t bytes)1599 static IMFSample *mfapi_create_sample(void *data, size_t bytes) 1600 { 1601 // Create media buffer 1602 IMFMediaBuffer *pBuffer = NULL; 1603 HRESULT hr = ::MFCreateMemoryBuffer(bytes, &pBuffer); 1604 if (!SUCCEEDED(hr)) 1605 return NULL; 1606 1607 // Lock the buffer and copy the video frame to the buffer. 1608 BYTE *pData = NULL; 1609 if (SUCCEEDED(hr)) 1610 hr = pBuffer->Lock(&pData, NULL, NULL); 1611 if (SUCCEEDED(hr)) 1612 { 1613 ::memcpy(pData, data, bytes); 1614 hr = pBuffer->Unlock(); 1615 } 1616 if (SUCCEEDED(hr)) 1617 hr = pBuffer->SetCurrentLength(bytes); 1618 1619 if (!SUCCEEDED(hr)) 1620 { 1621 pBuffer->Release(); 1622 return NULL; 1623 } 1624 1625 // Create sample 1626 IMFSample *pSample = NULL; 1627 hr = ::MFCreateSample(&pSample); 1628 if (!SUCCEEDED(hr)) 1629 { 1630 pBuffer->Release(); 1631 return NULL; 1632 } 1633 1634 // Bind buffer to sample and set sample parameters 1635 hr = pSample->AddBuffer(pBuffer); 1636 pBuffer->Release(); 1637 if (!SUCCEEDED(hr)) 1638 { 1639 pSample->Release(); 1640 return NULL; 1641 } 1642 1643 return pSample; 1644 } 1645 save_mfapi(const LSPString * path,size_t from,size_t max_count)1646 status_t AudioFile::save_mfapi(const LSPString *path, size_t from, size_t max_count) 1647 { 1648 // Create SinkWriter 1649 HRESULT hr; 1650 IMFSinkWriter *pSinkWriter = NULL; 1651 const WCHAR *wpath = path->get_utf16(); 1652 1653 // Create attributes 1654 IMFAttributes *pAttributes = NULL; 1655 hr = ::MFCreateAttributes(&pAttributes, 16); 1656 if (!SUCCEEDED(hr)) 1657 return STATUS_UNKNOWN_ERR; 1658 1659 if (SUCCEEDED(hr)) 1660 hr = pAttributes->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_WAVE); 1661 if (!SUCCEEDED(hr)) 1662 { 1663 pAttributes->Release(); 1664 return STATUS_UNKNOWN_ERR; 1665 } 1666 1667 // Create sink writer 1668 hr = ::MFCreateSinkWriterFromURL(wpath, NULL, pAttributes, &pSinkWriter); 1669 pAttributes->Release(); 1670 if (!SUCCEEDED(hr)) 1671 return STATUS_BAD_FORMAT; 1672 1673 // Initialize media type 1674 IMFMediaType *pMediaType = NULL; 1675 hr = ::MFCreateMediaType(&pMediaType); 1676 if (SUCCEEDED(hr)) 1677 hr = pMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); 1678 if (SUCCEEDED(hr)) 1679 hr = pMediaType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float); 1680 if (SUCCEEDED(hr)) 1681 hr = pMediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, sizeof(float) * 8); 1682 if (SUCCEEDED(hr)) 1683 hr = pMediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, pData->nChannels); 1684 if (SUCCEEDED(hr)) 1685 hr = pMediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, pData->nSampleRate); 1686 if (SUCCEEDED(hr)) 1687 hr = pMediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, pData->nChannels * sizeof(float) * pData->nSampleRate); 1688 1689 // hr = mt_aud_speech_in->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); 1690 // hr = mt_aud_speech_in->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM); 1691 // hr = mt_aud_speech_in->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, 2); 1692 // hr = mt_aud_speech_in->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16); 1693 // hr = mt_aud_speech_in->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4); 1694 // hr = mt_aud_speech_in->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100); 1695 // hr = mt_aud_speech_in->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100*2*2); 1696 1697 // Initialize output stream and input data format 1698 DWORD streamIndex; 1699 if (SUCCEEDED(hr)) 1700 hr = pSinkWriter->AddStream(pMediaType, &streamIndex); 1701 if (SUCCEEDED(hr)) 1702 hr = pSinkWriter->SetInputMediaType(streamIndex, pMediaType, NULL); 1703 if (pMediaType != NULL) 1704 pMediaType->Release(); 1705 1706 // Start writing 1707 if (SUCCEEDED(hr)) 1708 hr = pSinkWriter->BeginWriting(); 1709 1710 if (!SUCCEEDED(hr)) 1711 { 1712 pSinkWriter->Release(); 1713 return STATUS_BAD_FORMAT; 1714 } 1715 1716 // Allocate temporary buffer 1717 temporary_buffer_t *tb = create_temporary_buffer(pData, from); 1718 if (tb == NULL) 1719 { 1720 pSinkWriter->Release(); 1721 return STATUS_NO_MEM; 1722 } 1723 1724 wsize_t frame_id = 0; 1725 while ((max_count > 0) || (tb->nSize > 0)) 1726 { 1727 // Fill buffer 1728 max_count -= fill_temporary_buffer(tb, max_count); 1729 1730 // Flush buffer 1731 if (tb->nSize <= 0) 1732 continue; 1733 1734 // Write buffer to file 1735 size_t offset = 0; 1736 size_t frames = tb->nSize / tb->nFrameSize; 1737 while (offset < tb->nSize) 1738 { 1739 // Create audio sample for writing 1740 IMFSample *sample = mfapi_create_sample(&tb->bData[offset], frames * tb->nFrameSize); 1741 if (sample == NULL) 1742 { 1743 pSinkWriter->Release(); 1744 destroy_temporary_buffer(tb); 1745 return STATUS_UNKNOWN_ERR; 1746 } 1747 1748 // Update sample parameters 1749 hr = sample->SetSampleTime((frame_id * 100000000)/pData->nSampleRate); 1750 if (SUCCEEDED(hr)) 1751 hr = sample->SetSampleDuration((frames * 100000000)/pData->nSampleRate); 1752 if (SUCCEEDED(hr)) 1753 hr = pSinkWriter->WriteSample(streamIndex, sample); 1754 sample->Release(); 1755 1756 // Send the sample to the Sink Writer. 1757 if (!SUCCEEDED(hr)) 1758 { 1759 pSinkWriter->Release(); 1760 destroy_temporary_buffer(tb); 1761 return STATUS_UNKNOWN_ERR; 1762 } 1763 1764 // Update offsets 1765 offset += frames * tb->nFrameSize; 1766 frames -= frames; 1767 frame_id += frames; 1768 } 1769 1770 // Update buffer contents 1771 frames = tb->nSize - offset; 1772 if (frames > 0) 1773 ::memmove(tb->bData, &tb->bData[offset], frames); 1774 tb->nSize = frames; 1775 } 1776 1777 // Free allocated resources 1778 hr = pSinkWriter->Release(); 1779 destroy_temporary_buffer(tb); 1780 1781 return (SUCCEEDED(hr)) ? STATUS_OK : STATUS_UNKNOWN_ERR; 1782 } 1783 save_mmio(const LSPString * path,size_t from,size_t max_count)1784 status_t AudioFile::save_mmio(const LSPString *path, size_t from, size_t max_count) 1785 { 1786 WAVEFORMATEX fmt; 1787 HMMIO hmmioOut; 1788 MMCKINFO ckOut; 1789 MMCKINFO ckOutRIFF; 1790 MMIOINFO mmioinfoOut; 1791 int code; 1792 1793 // Initialize format descriptor 1794 fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; 1795 fmt.nChannels = pData->nChannels; 1796 fmt.nSamplesPerSec = pData->nSampleRate; 1797 fmt.nAvgBytesPerSec = pData->nChannels * pData->nSampleRate * sizeof(float); 1798 fmt.nBlockAlign = pData->nChannels * sizeof(float); 1799 fmt.wBitsPerSample = sizeof(float) * 8; 1800 fmt.cbSize = 0; 1801 1802 fmt.wFormatTag = CPU_TO_LE(fmt.wFormatTag); 1803 fmt.nChannels = CPU_TO_LE(fmt.nChannels); 1804 fmt.nSamplesPerSec = CPU_TO_LE(fmt.nSamplesPerSec); 1805 fmt.nAvgBytesPerSec = CPU_TO_LE(fmt.nAvgBytesPerSec); 1806 fmt.nBlockAlign = CPU_TO_LE(fmt.nBlockAlign); 1807 fmt.wBitsPerSample = CPU_TO_LE(fmt.wBitsPerSample); 1808 fmt.cbSize = CPU_TO_LE(fmt.cbSize); 1809 1810 // Create RIFF file 1811 status_t res = create_riff_file(path->get_utf16(), &fmt, &hmmioOut, &ckOut, &ckOutRIFF); 1812 if (res != STATUS_OK) 1813 return res; 1814 1815 // Create the 'data' chunk that holds the waveform samples. 1816 ckOut.ckid = mmioFOURCC('d', 'a', 't', 'a'); 1817 ckOut.cksize = 0; 1818 code = ::mmioCreateChunk(hmmioOut, &ckOut, 0); 1819 if (code == 0) 1820 code = ::mmioGetInfo(hmmioOut, &mmioinfoOut, 0); 1821 if (code != 0) 1822 { 1823 ::mmioClose(hmmioOut, 0); 1824 return STATUS_IO_ERROR; 1825 } 1826 1827 // Allocate temporary buffer 1828 temporary_buffer_t *tb = create_temporary_buffer(pData, from); 1829 if (tb == NULL) 1830 { 1831 ::mmioClose(hmmioOut, 0); 1832 return STATUS_NO_MEM; 1833 } 1834 1835 // Write file contents 1836 size_t samples = 0; 1837 1838 while ((max_count > 0) || (tb->nSize > 0)) 1839 { 1840 // Fill buffer 1841 size_t frames = fill_temporary_buffer(tb, max_count); 1842 max_count -= frames; 1843 if (tb->nSize <= 0) 1844 continue; 1845 1846 // Data is little-endian 1847 __IF_BE( byte_swap(reinterpret_cast<uint32_t *>(tb->bData), tb->nSize/sizeof(float)); ) 1848 1849 // Write temporary buffer 1850 size_t offset = 0; 1851 while (offset < tb->nSize) 1852 { 1853 // Write buffer to file 1854 size_t to_write = reinterpret_cast<uint8_t *>(mmioinfoOut.pchEndWrite) 1855 - reinterpret_cast<uint8_t *>(mmioinfoOut.pchNext); 1856 if (to_write <= 0) // We need to flush output buffer ? 1857 { 1858 mmioinfoOut.dwFlags |= MMIO_DIRTY; 1859 code = ::mmioAdvance(hmmioOut, &mmioinfoOut, MMIO_WRITE); 1860 if (code != 0) 1861 { 1862 destroy_temporary_buffer(tb); 1863 ::mmioClose(hmmioOut, 0); 1864 return STATUS_IO_ERROR; 1865 } 1866 1867 to_write = reinterpret_cast<uint8_t *>(mmioinfoOut.pchEndWrite) 1868 - reinterpret_cast<uint8_t *>(mmioinfoOut.pchNext); 1869 } 1870 1871 // Fill buffer with new data 1872 size_t bytes = tb->nSize - offset; 1873 if (to_write > bytes) 1874 to_write = bytes; 1875 uint8_t *dst = reinterpret_cast<uint8_t *>(mmioinfoOut.pchNext); 1876 ::memcpy(dst, &tb->bData[offset], to_write); 1877 mmioinfoOut.pchNext = reinterpret_cast<HPSTR>(dst + to_write); 1878 offset += to_write; 1879 } 1880 1881 // Clear size of temporary buffer 1882 samples += frames; 1883 tb->nSize = 0; 1884 } 1885 1886 // Destroy temporary buffer and flush file contents 1887 destroy_temporary_buffer(tb); 1888 mmioinfoOut.dwFlags |= MMIO_DIRTY; 1889 if ((code = ::mmioSetInfo(hmmioOut, &mmioinfoOut, 0)) != 0) 1890 { 1891 ::mmioClose(hmmioOut, 0); 1892 return STATUS_IO_ERROR; 1893 } 1894 1895 // Close file and complete write 1896 return complete_riff_file(&hmmioOut, &ckOut, &ckOutRIFF, &mmioinfoOut, samples); 1897 } 1898 load_mmio(const LSPString * path,float max_duration)1899 status_t AudioFile::load_mmio(const LSPString *path, float max_duration) 1900 { 1901 HMMIO hmmioIn; 1902 MMIOINFO mmioInfoIn; 1903 MMCKINFO ckInRiff; 1904 MMCKINFO ckIn; 1905 int error; 1906 status_t res; 1907 WAVEFORMATEX *pwfxInfo; 1908 WAVEFORMATEX dstInfo; 1909 HACMSTREAM acmStream; 1910 1911 // Open RIFF file 1912 res = open_riff_file(path->get_utf16(), &hmmioIn, &pwfxInfo, &ckInRiff); 1913 if (res != STATUS_OK) 1914 return res; 1915 1916 // Estimate maximum number of samples to read 1917 size_t srate = LE_TO_CPU(pwfxInfo->nSamplesPerSec); 1918 size_t samples = (max_duration >= 0.0f) ? seconds_to_samples(srate, max_duration) : size_t(-1); 1919 lsp_trace("file parameters: channels=%d, sample_rate=%d max_duration=%.3f", 1920 int(LE_TO_CPU(pwfxInfo->nChannels)), 1921 int(LE_TO_CPU(pwfxInfo->nSamplesPerSec)), 1922 max_duration 1923 ); 1924 1925 // Perform a seek to data 1926 if ((error = ::mmioSeek(hmmioIn, LE_TO_CPU(ckInRiff.dwDataOffset) + sizeof(FOURCC), SEEK_SET)) == -1) 1927 { 1928 ::mmioClose(hmmioIn, 0); 1929 return STATUS_BAD_FORMAT; 1930 } 1931 ckIn.ckid = mmioFOURCC('d', 'a', 't', 'a'); 1932 if ((error = ::mmioDescend(hmmioIn, &ckIn, &ckInRiff, MMIO_FINDCHUNK)) != 0) 1933 { 1934 ::mmioClose(hmmioIn, 0); 1935 return STATUS_BAD_FORMAT; 1936 } 1937 if ((error = ::mmioGetInfo(hmmioIn, &mmioInfoIn, 0)) != 0) 1938 { 1939 ::mmioClose(hmmioIn, 0); 1940 return STATUS_IO_ERROR; 1941 } 1942 1943 // Some magic with computing 1944 size_t bytes = LE_TO_CPU(ckIn.cksize); 1945 size_t channels = LE_TO_CPU(pwfxInfo->nChannels); 1946 if (bytes > LE_TO_CPU(ckIn.cksize)) 1947 bytes = LE_TO_CPU(ckIn.cksize); 1948 1949 // We are ready to read but first initialize ACM stream 1950 dstInfo.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; 1951 dstInfo.nChannels = channels; 1952 dstInfo.nSamplesPerSec = LE_TO_CPU(pwfxInfo->nSamplesPerSec); 1953 dstInfo.nAvgBytesPerSec = dstInfo.nSamplesPerSec * dstInfo.nChannels * sizeof(float); 1954 dstInfo.nBlockAlign = dstInfo.nChannels * sizeof(float); 1955 dstInfo.wBitsPerSample = sizeof(float) * 8; 1956 dstInfo.cbSize = 0; 1957 1958 dstInfo.wFormatTag = CPU_TO_LE(dstInfo.wFormatTag); 1959 dstInfo.nChannels = CPU_TO_LE(dstInfo.nChannels); 1960 dstInfo.nSamplesPerSec = CPU_TO_LE(dstInfo.nSamplesPerSec); 1961 dstInfo.nAvgBytesPerSec = CPU_TO_LE(dstInfo.nAvgBytesPerSec); 1962 dstInfo.nBlockAlign = CPU_TO_LE(dstInfo.nBlockAlign); 1963 dstInfo.wBitsPerSample = CPU_TO_LE(dstInfo.wBitsPerSample); 1964 dstInfo.cbSize = CPU_TO_LE(dstInfo.cbSize); 1965 1966 // Open and configure ACM stream 1967 if ((error = ::acmStreamOpen(&acmStream, NULL, pwfxInfo, &dstInfo, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME)) != 0) 1968 { 1969 ::mmioClose(hmmioIn, 0); 1970 switch (error) 1971 { 1972 case ACMERR_NOTPOSSIBLE: return STATUS_BAD_FORMAT; 1973 case STATUS_NO_MEM: return STATUS_NO_MEM; 1974 default: return STATUS_UNKNOWN_ERR; 1975 } 1976 } 1977 1978 ACMSTREAMHEADER streamHead; 1979 ::bzero(&streamHead, sizeof(ACMSTREAMHEADER)); 1980 1981 streamHead.cbStruct = sizeof(ACMSTREAMHEADER); 1982 streamHead.cbSrcLength = ACM_INPUT_BUFSIZE; 1983 streamHead.pbSrc = reinterpret_cast<PBYTE>(::malloc(streamHead.cbSrcLength)); 1984 if (streamHead.pbSrc == NULL) 1985 { 1986 ::acmStreamClose(acmStream, 0); 1987 ::mmioClose(hmmioIn, 0); 1988 return STATUS_NO_MEM; 1989 } 1990 1991 error = ::acmStreamSize(acmStream, ACM_INPUT_BUFSIZE, &streamHead.cbDstLength, ACM_STREAMSIZEF_SOURCE); 1992 if ((error != 0) || (streamHead.cbDstLength <= 0)) 1993 { 1994 ::free(streamHead.pbSrc); 1995 ::acmStreamClose(acmStream, 0); 1996 ::mmioClose(hmmioIn, 0); 1997 return STATUS_UNKNOWN_ERR; 1998 } 1999 2000 streamHead.pbDst = reinterpret_cast<PBYTE>(::malloc(streamHead.cbDstLength)); 2001 if (streamHead.pbDst == NULL) 2002 { 2003 ::free(streamHead.pbSrc); 2004 ::acmStreamClose(acmStream, 0); 2005 ::mmioClose(hmmioIn, 0); 2006 return STATUS_NO_MEM; 2007 } 2008 2009 if ((error = acmStreamPrepareHeader( acmStream, &streamHead, 0 )) != 0) 2010 { 2011 ::free(streamHead.pbSrc); 2012 ::free(streamHead.pbDst); 2013 ::acmStreamClose(acmStream, 0); 2014 ::mmioClose(hmmioIn, 0); 2015 return STATUS_BAD_FORMAT; 2016 } 2017 2018 // Create file content for storage 2019 file_content_t *data = create_file_content(channels, 1024); 2020 if (!data) 2021 { 2022 ::free(streamHead.pbSrc); 2023 ::free(streamHead.pbDst); 2024 ::acmStreamClose(acmStream, 0); 2025 ::mmioClose(hmmioIn, 0); 2026 return STATUS_NO_MEM; 2027 } 2028 2029 // Perform read + decode 2030 // https://gist.github.com/dweekly/633367 2031 size_t bread = 0, fread = 0; // Number of bytes read, number of frames read 2032 bool eof = false; 2033 2034 while (true) 2035 { 2036 // We have read enough data? 2037 if ((max_duration >= 0.0f) && (fread >= samples)) 2038 break; 2039 2040 // Try to maximize input buffer size 2041 if ((streamHead.cbSrcLength < ACM_INPUT_BUFSIZE) && (!eof)) 2042 { 2043 size_t avail = reinterpret_cast<uint8_t *>(mmioInfoIn.pchEndRead) 2044 - reinterpret_cast<uint8_t *>(mmioInfoIn.pchNext); 2045 if (avail > 0) 2046 { 2047 // Fill buffer 2048 size_t to_copy = ACM_INPUT_BUFSIZE - streamHead.cbSrcLength; 2049 if (to_copy > avail) 2050 to_copy = avail; 2051 ::memcpy(&streamHead.pbSrc[streamHead.cbSrcLength], mmioInfoIn.pchNext, to_copy); 2052 mmioInfoIn.pchNext = reinterpret_cast<HPSTR>(reinterpret_cast<uint8_t *>(mmioInfoIn.pchNext) + to_copy); 2053 continue; 2054 } 2055 else if (bread >= bytes) 2056 { 2057 eof = true; 2058 continue; 2059 } 2060 2061 // Try to read from MMIO 2062 error = ::mmioAdvance(hmmioIn, &mmioInfoIn, MMIO_READ); 2063 if ((error != 0) || (mmioInfoIn.pchNext == mmioInfoIn.pchEndRead)) 2064 { 2065 destroy_file_content(data); 2066 ::free(streamHead.pbSrc); 2067 ::free(streamHead.pbDst); 2068 ::acmStreamUnprepareHeader(acmStream, &streamHead, 0); 2069 ::acmStreamClose(acmStream, 0); 2070 ::mmioClose(hmmioIn, 0); 2071 return STATUS_BAD_FORMAT; 2072 } 2073 2074 // Update number of bytes read from RIFF file 2075 bread += reinterpret_cast<uint8_t *>(mmioInfoIn.pchEndRead) 2076 - reinterpret_cast<uint8_t *>(mmioInfoIn.pchNext); 2077 } 2078 else if (streamHead.cbSrcLength > 0) 2079 { 2080 // Perform conversion 2081 size_t flags = (eof) ? 0 : ACM_STREAMCONVERTF_BLOCKALIGN; 2082 if ((error = ::acmStreamConvert(acmStream, &streamHead, flags)) != 0) 2083 { 2084 destroy_file_content(data); 2085 ::free(streamHead.pbSrc); 2086 ::free(streamHead.pbDst); 2087 ::acmStreamUnprepareHeader(acmStream, &streamHead, 0); 2088 ::acmStreamClose(acmStream, 0); 2089 ::mmioClose(hmmioIn, 0); 2090 return STATUS_UNKNOWN_ERR; 2091 } 2092 2093 // Advance the input buffer pointer 2094 size_t delta = streamHead.cbSrcLength - streamHead.cbSrcLengthUsed; 2095 if (delta > 0) 2096 ::memmove(streamHead.pbSrc, &streamHead.pbSrc[streamHead.cbSrcLengthUsed], delta); 2097 streamHead.cbSrcLength = delta; 2098 streamHead.cbSrcLengthUsed = 0; 2099 2100 // Invalid data at output? 2101 size_t frames = streamHead.cbDstLengthUsed / (sizeof(float) * channels); 2102 if ((frames * sizeof(float) * channels) != streamHead.cbDstLengthUsed) 2103 { 2104 destroy_file_content(data); 2105 ::free(streamHead.pbSrc); 2106 ::free(streamHead.pbDst); 2107 ::acmStreamUnprepareHeader(acmStream, &streamHead, 0); 2108 ::acmStreamClose(acmStream, 0); 2109 ::mmioClose(hmmioIn, 0); 2110 return STATUS_CORRUPTED_FILE; 2111 } 2112 2113 // Commit decoded data to the output file 2114 float *fsamples = reinterpret_cast<float *>(streamHead.pbDst); 2115 __IF_BE( dsp::swap_bytes(fsamples, frames * channels) ); 2116 if ((max_duration >= 0.0f) && (frames > samples)) 2117 frames = samples; 2118 size_t nfread = fread + frames; 2119 2120 // Ensure that we have enough space for growing 2121 file_content_t *ndata = grow_file_content(data, nfread); 2122 if (ndata == NULL) 2123 { 2124 destroy_file_content(data); 2125 ::free(streamHead.pbSrc); 2126 ::free(streamHead.pbDst); 2127 ::acmStreamUnprepareHeader(acmStream, &streamHead, 0); 2128 ::acmStreamClose(acmStream, 0); 2129 ::mmioClose(hmmioIn, 0); 2130 return STATUS_NO_MEM; 2131 } 2132 data = ndata; 2133 2134 // Process each frame (de-interleave) 2135 for (size_t i=0; i<channels; ++i) 2136 { 2137 const float *src = &fsamples[i]; 2138 float *dst = data->vChannels[i]; 2139 for (size_t j=0; j<frames; ++j, src += channels, ++dst) 2140 *dst = *src; 2141 } 2142 fread = nfread; // Update number of read frames 2143 2144 // Advance the output buffer pointer 2145 delta = streamHead.cbDstLengthUsed - frames * (sizeof(float) * channels); 2146 if (delta > 0) 2147 ::memmove(streamHead.pbDst, &streamHead.pbDst[streamHead.cbDstLengthUsed], delta); 2148 streamHead.cbSrcLength = delta; 2149 streamHead.cbDstLengthUsed = 0; 2150 } 2151 else // No more data to convert? 2152 { 2153 eof = true; 2154 break; 2155 } 2156 } 2157 2158 // Free ACM headers and close ACM stream 2159 ::free(streamHead.pbSrc); 2160 ::free(streamHead.pbDst); 2161 if ((error = ::acmStreamUnprepareHeader(acmStream, &streamHead, 0)) != 0) 2162 { 2163 destroy_file_content(data); 2164 ::acmStreamClose(acmStream, 0); 2165 ::mmioClose(hmmioIn, 0); 2166 return STATUS_UNKNOWN_ERR; 2167 } 2168 if ((error = ::acmStreamUnprepareHeader(acmStream, &streamHead, 0)) != 0) 2169 { 2170 destroy_file_content(data); 2171 ::mmioClose(hmmioIn, 0); 2172 return STATUS_UNKNOWN_ERR; 2173 } 2174 2175 // Complete reading 2176 if ((error = ::mmioSetInfo(hmmioIn, &mmioInfoIn, 0)) != 0) 2177 { 2178 destroy_file_content(data); 2179 ::mmioClose(hmmioIn, 0); 2180 return STATUS_IO_ERROR; 2181 } 2182 if ((error = ::mmioClose(hmmioIn, 0)) != 0) 2183 { 2184 destroy_file_content(data); 2185 return STATUS_IO_ERROR; 2186 } 2187 2188 // Success read, destroy previously used content and store new 2189 if (pData != NULL) 2190 destroy_file_content(pData); 2191 pData = data; 2192 2193 return STATUS_OK; 2194 } 2195 2196 #else 2197 decode_sf_error(SNDFILE * fd)2198 static status_t decode_sf_error(SNDFILE *fd) 2199 { 2200 switch (sf_error(NULL)) 2201 { 2202 case SF_ERR_NO_ERROR: 2203 return STATUS_OK; 2204 case SF_ERR_UNRECOGNISED_FORMAT: 2205 return STATUS_BAD_FORMAT; 2206 case SF_ERR_MALFORMED_FILE: 2207 return STATUS_CORRUPTED_FILE; 2208 case SF_ERR_UNSUPPORTED_ENCODING: 2209 return STATUS_BAD_FORMAT; 2210 default: 2211 return STATUS_UNKNOWN_ERR; 2212 } 2213 } 2214 load_sndfile(const LSPString * path,float max_duration)2215 status_t AudioFile::load_sndfile(const LSPString *path, float max_duration) 2216 { 2217 // Load sound file 2218 SNDFILE *sf_obj; 2219 SF_INFO sf_info; 2220 2221 // Open sound file 2222 lsp_trace("loading file: %s\n", path->get_native()); 2223 if ((sf_obj = sf_open(path->get_native(), SFM_READ, &sf_info)) == NULL) 2224 return decode_sf_error(sf_obj); 2225 2226 // Read sample file 2227 ssize_t max_samples = (max_duration >= 0.0f) ? seconds_to_samples(sf_info.samplerate, max_duration) : -1; 2228 lsp_trace("file parameters: frames=%d, channels=%d, sample_rate=%d max_duration=%.3f\n, max_samples=%d", 2229 int(sf_info.frames), int(sf_info.channels), int(sf_info.samplerate), max_duration, int(max_samples)); 2230 2231 // Patch sf_info 2232 if ((max_samples >= 0) && (sf_info.frames > sf_count_t(max_samples))) 2233 sf_info.frames = max_samples; 2234 2235 // Create file content 2236 file_content_t *fc = create_file_content(sf_info.channels, sf_info.frames); 2237 if (fc == NULL) 2238 { 2239 sf_close(sf_obj); 2240 return STATUS_NO_MEM; 2241 } 2242 fc->nSampleRate = sf_info.samplerate; 2243 2244 // Allocate temporary buffer 2245 temporary_buffer_t *tb = create_temporary_buffer(fc); 2246 if (tb == NULL) 2247 { 2248 destroy_file_content(fc); 2249 sf_close(sf_obj); 2250 return STATUS_NO_MEM; 2251 } 2252 2253 size_t count = sf_info.frames; 2254 while (count > 0) 2255 { 2256 // Determine how many data is available to read 2257 size_t can_read = (tb->nCapacity - tb->nSize) / tb->nFrameSize; 2258 if (can_read <= 0) 2259 { 2260 flush_temporary_buffer(tb); 2261 can_read = (tb->nCapacity - tb->nSize) / tb->nFrameSize; 2262 } 2263 2264 // Calculate amount of samples to read 2265 size_t to_read = (count > can_read) ? can_read : count; 2266 sf_count_t amount = sf_readf_float(sf_obj, reinterpret_cast<float *>(&tb->bData[tb->nSize]), to_read); 2267 if (amount <= 0) 2268 { 2269 status_t status = decode_sf_error(sf_obj); 2270 2271 destroy_temporary_buffer(tb); 2272 destroy_file_content(fc); 2273 sf_close(sf_obj); 2274 2275 return status; 2276 } 2277 2278 // Update counters 2279 tb->nSize += amount * tb->nFrameSize; 2280 count -= amount; 2281 } 2282 2283 // Flush last read data (if present) 2284 flush_temporary_buffer(tb); 2285 2286 // Free allocated resources 2287 destroy_temporary_buffer(tb); 2288 sf_close(sf_obj); 2289 2290 // Destroy previously used content and store new 2291 if (pData != NULL) 2292 destroy_file_content(pData); 2293 pData = fc; 2294 2295 return STATUS_OK; 2296 } 2297 save_sndfile(const LSPString * path,size_t from,size_t max_count)2298 status_t AudioFile::save_sndfile(const LSPString *path, size_t from, size_t max_count) 2299 { 2300 if (pData == NULL) 2301 return STATUS_NO_DATA; 2302 2303 // Load sound file 2304 SNDFILE *sf_obj; 2305 SF_INFO sf_info; 2306 2307 sf_info.frames = max_count; 2308 sf_info.samplerate = pData->nSampleRate; 2309 sf_info.channels = pData->nChannels; 2310 sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT | SF_ENDIAN_LITTLE; 2311 sf_info.sections = 0; 2312 sf_info.seekable = 0; 2313 2314 if (sf_info.frames > sf_count_t(pData->nSamples - from)) 2315 sf_info.frames = pData->nSamples - from; 2316 2317 // Open sound file 2318 lsp_trace("storing file: %s\n", path->get_native()); 2319 if ((sf_obj = sf_open(path->get_native(), SFM_WRITE, &sf_info)) == NULL) 2320 { 2321 lsp_trace("Error: %s", sf_strerror(sf_obj)); 2322 return decode_sf_error(NULL); 2323 } 2324 2325 // Allocate temporary buffer 2326 temporary_buffer_t *tb = create_temporary_buffer(pData, from); 2327 if (tb == NULL) 2328 return STATUS_NO_MEM; 2329 2330 while ((max_count > 0) || (tb->nSize > 0)) 2331 { 2332 // Fill buffer 2333 max_count -= fill_temporary_buffer(tb, max_count); 2334 2335 // Flush buffer 2336 if (tb->nSize > 0) 2337 { 2338 // Write buffer to file 2339 size_t offset = 0; 2340 size_t frames = tb->nSize / tb->nFrameSize; 2341 while (offset < tb->nSize) 2342 { 2343 sf_count_t written = sf_writef_float(sf_obj, reinterpret_cast<float *>(&tb->bData[offset]), frames); 2344 if (written < 0) 2345 { 2346 status_t status = decode_sf_error(sf_obj); 2347 sf_close(sf_obj); 2348 destroy_temporary_buffer(tb); 2349 return status; 2350 } 2351 offset += written * tb->nFrameSize; 2352 frames -= written; 2353 } 2354 2355 // Update buffer contents 2356 frames = tb->nSize - offset; 2357 if (frames > 0) 2358 ::memmove(tb->bData, &tb->bData[offset], frames); 2359 tb->nSize = frames; 2360 } 2361 } 2362 2363 // Free allocated resources 2364 sf_close(sf_obj); 2365 destroy_temporary_buffer(tb); 2366 2367 return STATUS_OK; 2368 } 2369 #endif /* PLATFORM_WINDOWS */ 2370 2371 } /* namespace lsp */ 2372