348 |
} |
} |
349 |
FrameOffset = 0; // just for streaming compressed samples |
FrameOffset = 0; // just for streaming compressed samples |
350 |
|
|
351 |
LoopSize = LoopEnd - LoopStart; |
LoopSize = LoopEnd - LoopStart + 1; |
352 |
} |
} |
353 |
|
|
354 |
/** |
/** |
722 |
* @param SampleCount number of sample points to read |
* @param SampleCount number of sample points to read |
723 |
* @param pPlaybackState will be used to store and reload the playback |
* @param pPlaybackState will be used to store and reload the playback |
724 |
* state for the next ReadAndLoop() call |
* state for the next ReadAndLoop() call |
725 |
|
* @param pDimRgn dimension region with looping information |
726 |
* @param pExternalDecompressionBuffer (optional) external buffer to use for decompression |
* @param pExternalDecompressionBuffer (optional) external buffer to use for decompression |
727 |
* @returns number of successfully read sample points |
* @returns number of successfully read sample points |
728 |
* @see CreateDecompressionBuffer() |
* @see CreateDecompressionBuffer() |
729 |
*/ |
*/ |
730 |
unsigned long Sample::ReadAndLoop(void* pBuffer, unsigned long SampleCount, playback_state_t* pPlaybackState, buffer_t* pExternalDecompressionBuffer) { |
unsigned long Sample::ReadAndLoop(void* pBuffer, unsigned long SampleCount, playback_state_t* pPlaybackState, |
731 |
|
DimensionRegion* pDimRgn, buffer_t* pExternalDecompressionBuffer) { |
732 |
unsigned long samplestoread = SampleCount, totalreadsamples = 0, readsamples, samplestoloopend; |
unsigned long samplestoread = SampleCount, totalreadsamples = 0, readsamples, samplestoloopend; |
733 |
uint8_t* pDst = (uint8_t*) pBuffer; |
uint8_t* pDst = (uint8_t*) pBuffer; |
734 |
|
|
735 |
SetPos(pPlaybackState->position); // recover position from the last time |
SetPos(pPlaybackState->position); // recover position from the last time |
736 |
|
|
737 |
if (this->Loops && GetPos() <= this->LoopEnd) { // honor looping if there are loop points defined |
if (pDimRgn->SampleLoops) { // honor looping if there are loop points defined |
738 |
|
|
739 |
switch (this->LoopType) { |
const DLS::sample_loop_t& loop = pDimRgn->pSampleLoops[0]; |
740 |
|
const uint32_t loopEnd = loop.LoopStart + loop.LoopLength; |
741 |
|
|
742 |
case loop_type_bidirectional: { //TODO: not tested yet! |
if (GetPos() <= loopEnd) { |
743 |
do { |
switch (loop.LoopType) { |
|
// if not endless loop check if max. number of loop cycles have been passed |
|
|
if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break; |
|
|
|
|
|
if (!pPlaybackState->reverse) { // forward playback |
|
|
do { |
|
|
samplestoloopend = this->LoopEnd - GetPos(); |
|
|
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer); |
|
|
samplestoread -= readsamples; |
|
|
totalreadsamples += readsamples; |
|
|
if (readsamples == samplestoloopend) { |
|
|
pPlaybackState->reverse = true; |
|
|
break; |
|
|
} |
|
|
} while (samplestoread && readsamples); |
|
|
} |
|
|
else { // backward playback |
|
744 |
|
|
745 |
// as we can only read forward from disk, we have to |
case loop_type_bidirectional: { //TODO: not tested yet! |
746 |
// determine the end position within the loop first, |
do { |
747 |
// read forward from that 'end' and finally after |
// if not endless loop check if max. number of loop cycles have been passed |
748 |
// reading, swap all sample frames so it reflects |
if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break; |
749 |
// backward playback |
|
750 |
|
if (!pPlaybackState->reverse) { // forward playback |
751 |
unsigned long swapareastart = totalreadsamples; |
do { |
752 |
unsigned long loopoffset = GetPos() - this->LoopStart; |
samplestoloopend = loopEnd - GetPos(); |
753 |
unsigned long samplestoreadinloop = Min(samplestoread, loopoffset); |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer); |
754 |
unsigned long reverseplaybackend = GetPos() - samplestoreadinloop; |
samplestoread -= readsamples; |
755 |
|
totalreadsamples += readsamples; |
756 |
SetPos(reverseplaybackend); |
if (readsamples == samplestoloopend) { |
757 |
|
pPlaybackState->reverse = true; |
758 |
// read samples for backward playback |
break; |
759 |
do { |
} |
760 |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], samplestoreadinloop, pExternalDecompressionBuffer); |
} while (samplestoread && readsamples); |
761 |
samplestoreadinloop -= readsamples; |
} |
762 |
samplestoread -= readsamples; |
else { // backward playback |
|
totalreadsamples += readsamples; |
|
|
} while (samplestoreadinloop && readsamples); |
|
763 |
|
|
764 |
SetPos(reverseplaybackend); // pretend we really read backwards |
// as we can only read forward from disk, we have to |
765 |
|
// determine the end position within the loop first, |
766 |
|
// read forward from that 'end' and finally after |
767 |
|
// reading, swap all sample frames so it reflects |
768 |
|
// backward playback |
769 |
|
|
770 |
|
unsigned long swapareastart = totalreadsamples; |
771 |
|
unsigned long loopoffset = GetPos() - loop.LoopStart; |
772 |
|
unsigned long samplestoreadinloop = Min(samplestoread, loopoffset); |
773 |
|
unsigned long reverseplaybackend = GetPos() - samplestoreadinloop; |
774 |
|
|
775 |
|
SetPos(reverseplaybackend); |
776 |
|
|
777 |
|
// read samples for backward playback |
778 |
|
do { |
779 |
|
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], samplestoreadinloop, pExternalDecompressionBuffer); |
780 |
|
samplestoreadinloop -= readsamples; |
781 |
|
samplestoread -= readsamples; |
782 |
|
totalreadsamples += readsamples; |
783 |
|
} while (samplestoreadinloop && readsamples); |
784 |
|
|
785 |
|
SetPos(reverseplaybackend); // pretend we really read backwards |
786 |
|
|
787 |
|
if (reverseplaybackend == loop.LoopStart) { |
788 |
|
pPlaybackState->loop_cycles_left--; |
789 |
|
pPlaybackState->reverse = false; |
790 |
|
} |
791 |
|
|
792 |
if (reverseplaybackend == this->LoopStart) { |
// reverse the sample frames for backward playback |
793 |
pPlaybackState->loop_cycles_left--; |
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
|
pPlaybackState->reverse = false; |
|
794 |
} |
} |
795 |
|
} while (samplestoread && readsamples); |
796 |
|
break; |
797 |
|
} |
798 |
|
|
799 |
// reverse the sample frames for backward playback |
case loop_type_backward: { // TODO: not tested yet! |
800 |
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
// forward playback (not entered the loop yet) |
801 |
} |
if (!pPlaybackState->reverse) do { |
802 |
} while (samplestoread && readsamples); |
samplestoloopend = loopEnd - GetPos(); |
803 |
break; |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer); |
804 |
} |
samplestoread -= readsamples; |
805 |
|
totalreadsamples += readsamples; |
806 |
case loop_type_backward: { // TODO: not tested yet! |
if (readsamples == samplestoloopend) { |
807 |
// forward playback (not entered the loop yet) |
pPlaybackState->reverse = true; |
808 |
if (!pPlaybackState->reverse) do { |
break; |
809 |
samplestoloopend = this->LoopEnd - GetPos(); |
} |
810 |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer); |
} while (samplestoread && readsamples); |
|
samplestoread -= readsamples; |
|
|
totalreadsamples += readsamples; |
|
|
if (readsamples == samplestoloopend) { |
|
|
pPlaybackState->reverse = true; |
|
|
break; |
|
|
} |
|
|
} while (samplestoread && readsamples); |
|
811 |
|
|
812 |
if (!samplestoread) break; |
if (!samplestoread) break; |
813 |
|
|
814 |
// as we can only read forward from disk, we have to |
// as we can only read forward from disk, we have to |
815 |
// determine the end position within the loop first, |
// determine the end position within the loop first, |
816 |
// read forward from that 'end' and finally after |
// read forward from that 'end' and finally after |
817 |
// reading, swap all sample frames so it reflects |
// reading, swap all sample frames so it reflects |
818 |
// backward playback |
// backward playback |
819 |
|
|
820 |
unsigned long swapareastart = totalreadsamples; |
unsigned long swapareastart = totalreadsamples; |
821 |
unsigned long loopoffset = GetPos() - this->LoopStart; |
unsigned long loopoffset = GetPos() - loop.LoopStart; |
822 |
unsigned long samplestoreadinloop = (this->LoopPlayCount) ? Min(samplestoread, pPlaybackState->loop_cycles_left * LoopSize - loopoffset) |
unsigned long samplestoreadinloop = (this->LoopPlayCount) ? Min(samplestoread, pPlaybackState->loop_cycles_left * loop.LoopLength - loopoffset) |
823 |
: samplestoread; |
: samplestoread; |
824 |
unsigned long reverseplaybackend = this->LoopStart + Abs((loopoffset - samplestoreadinloop) % this->LoopSize); |
unsigned long reverseplaybackend = loop.LoopStart + Abs((loopoffset - samplestoreadinloop) % loop.LoopLength); |
825 |
|
|
826 |
SetPos(reverseplaybackend); |
SetPos(reverseplaybackend); |
827 |
|
|
828 |
// read samples for backward playback |
// read samples for backward playback |
829 |
do { |
do { |
830 |
// if not endless loop check if max. number of loop cycles have been passed |
// if not endless loop check if max. number of loop cycles have been passed |
831 |
if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break; |
if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break; |
832 |
samplestoloopend = this->LoopEnd - GetPos(); |
samplestoloopend = loopEnd - GetPos(); |
833 |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoreadinloop, samplestoloopend), pExternalDecompressionBuffer); |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoreadinloop, samplestoloopend), pExternalDecompressionBuffer); |
834 |
samplestoreadinloop -= readsamples; |
samplestoreadinloop -= readsamples; |
835 |
samplestoread -= readsamples; |
samplestoread -= readsamples; |
836 |
totalreadsamples += readsamples; |
totalreadsamples += readsamples; |
837 |
if (readsamples == samplestoloopend) { |
if (readsamples == samplestoloopend) { |
838 |
pPlaybackState->loop_cycles_left--; |
pPlaybackState->loop_cycles_left--; |
839 |
SetPos(this->LoopStart); |
SetPos(loop.LoopStart); |
840 |
} |
} |
841 |
} while (samplestoreadinloop && readsamples); |
} while (samplestoreadinloop && readsamples); |
842 |
|
|
843 |
SetPos(reverseplaybackend); // pretend we really read backwards |
SetPos(reverseplaybackend); // pretend we really read backwards |
844 |
|
|
845 |
// reverse the sample frames for backward playback |
// reverse the sample frames for backward playback |
846 |
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize); |
847 |
break; |
break; |
848 |
} |
} |
849 |
|
|
850 |
default: case loop_type_normal: { |
default: case loop_type_normal: { |
851 |
do { |
do { |
852 |
// if not endless loop check if max. number of loop cycles have been passed |
// if not endless loop check if max. number of loop cycles have been passed |
853 |
if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break; |
if (this->LoopPlayCount && !pPlaybackState->loop_cycles_left) break; |
854 |
samplestoloopend = this->LoopEnd - GetPos(); |
samplestoloopend = loopEnd - GetPos(); |
855 |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer); |
readsamples = Read(&pDst[totalreadsamples * this->FrameSize], Min(samplestoread, samplestoloopend), pExternalDecompressionBuffer); |
856 |
samplestoread -= readsamples; |
samplestoread -= readsamples; |
857 |
totalreadsamples += readsamples; |
totalreadsamples += readsamples; |
858 |
if (readsamples == samplestoloopend) { |
if (readsamples == samplestoloopend) { |
859 |
pPlaybackState->loop_cycles_left--; |
pPlaybackState->loop_cycles_left--; |
860 |
SetPos(this->LoopStart); |
SetPos(loop.LoopStart); |
861 |
} |
} |
862 |
} while (samplestoread && readsamples); |
} while (samplestoread && readsamples); |
863 |
break; |
break; |
864 |
|
} |
865 |
} |
} |
866 |
} |
} |
867 |
} |
} |
2090 |
pDimensionDefinitions[i].split_type = (dimension == dimension_layer || |
pDimensionDefinitions[i].split_type = (dimension == dimension_layer || |
2091 |
dimension == dimension_samplechannel || |
dimension == dimension_samplechannel || |
2092 |
dimension == dimension_releasetrigger || |
dimension == dimension_releasetrigger || |
2093 |
|
dimension == dimension_keyboard || |
2094 |
dimension == dimension_roundrobin || |
dimension == dimension_roundrobin || |
2095 |
dimension == dimension_random) ? split_type_bit |
dimension == dimension_random) ? split_type_bit |
2096 |
: split_type_normal; |
: split_type_normal; |