| 652 | } |
| 653 | |
| 654 | size_t Audio::resample(unsigned destinationChannels, unsigned destinationSampleRate, int16_t* destinationBuffer, size_t destinationBufferSize, double velocity) { |
| 655 | unsigned destinationSamples = destinationBufferSize / destinationChannels; |
| 656 | if (destinationSamples == 0) |
| 657 | return 0; |
| 658 | |
| 659 | unsigned sourceChannels = channels(); |
| 660 | unsigned sourceSampleRate = sampleRate(); |
| 661 | |
| 662 | if (velocity != 1.0) |
| 663 | sourceSampleRate = (unsigned)(sourceSampleRate * velocity); |
| 664 | |
| 665 | if (destinationChannels == sourceChannels && destinationSampleRate == sourceSampleRate) { |
| 666 | // If the destination and source channel count and sample rate are the |
| 667 | // same, this is the same as a read. |
| 668 | |
| 669 | return read(destinationBuffer, destinationBufferSize); |
| 670 | |
| 671 | } else if (destinationSampleRate == sourceSampleRate) { |
| 672 | // If the destination and source sample rate are the same, then we can skip |
| 673 | // the super-sampling math. |
| 674 | |
| 675 | unsigned sourceBufferSize = destinationSamples * sourceChannels; |
| 676 | |
| 677 | m_workingBuffer.resize(sourceBufferSize * sizeof(int16_t)); |
| 678 | int16_t* sourceBuffer = (int16_t*)m_workingBuffer.ptr(); |
| 679 | |
| 680 | unsigned readSamples = read(sourceBuffer, sourceBufferSize) / sourceChannels; |
| 681 | |
| 682 | for (unsigned sample = 0; sample < readSamples; ++sample) { |
| 683 | unsigned sourceBufferIndex = sample * sourceChannels; |
| 684 | unsigned destinationBufferIndex = sample * destinationChannels; |
| 685 | |
| 686 | for (unsigned destinationChannel = 0; destinationChannel < destinationChannels; ++destinationChannel) { |
| 687 | // If the destination channel count is greater than the source |
| 688 | // channels, simply copy the last channel |
| 689 | unsigned sourceChannel = min(destinationChannel, sourceChannels - 1); |
| 690 | destinationBuffer[destinationBufferIndex + destinationChannel] = |
| 691 | sourceBuffer[sourceBufferIndex + sourceChannel]; |
| 692 | } |
| 693 | } |
| 694 | |
| 695 | return readSamples * destinationChannels; |
| 696 | |
| 697 | } else { |
| 698 | // Otherwise, we have to do a full resample. |
| 699 | |
| 700 | unsigned sourceSamples = ((uint64_t)sourceSampleRate * destinationSamples + destinationSampleRate - 1) / destinationSampleRate; |
| 701 | unsigned sourceBufferSize = sourceSamples * sourceChannels; |
| 702 | |
| 703 | m_workingBuffer.resize(sourceBufferSize * sizeof(int16_t)); |
| 704 | int16_t* sourceBuffer = (int16_t*)m_workingBuffer.ptr(); |
| 705 | |
| 706 | unsigned readSamples = read(sourceBuffer, sourceBufferSize) / sourceChannels; |
| 707 | |
| 708 | if (readSamples == 0) |
| 709 | return 0; |
| 710 | |
| 711 | unsigned writtenSamples = 0; |