61 |
|
|
62 |
// select synthesis implementation (currently either pure C++ or MMX+SSE(1)) |
// select synthesis implementation (currently either pure C++ or MMX+SSE(1)) |
63 |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); |
SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); |
64 |
|
SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true); |
65 |
} |
} |
66 |
|
|
67 |
Voice::~Voice() { |
Voice::~Voice() { |
696 |
Pos -= int(Pos); |
Pos -= int(Pos); |
697 |
} |
} |
698 |
|
|
699 |
|
const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace(); |
700 |
|
|
701 |
// add silence sample at the end if we reached the end of the stream (for the interpolator) |
// add silence sample at the end if we reached the end of the stream (for the interpolator) |
702 |
if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) { |
if (DiskStreamRef.State == Stream::state_end) { |
703 |
DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels); |
const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm |
704 |
this->PlaybackState = playback_state_end; |
if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) { |
705 |
|
DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead); |
706 |
|
} |
707 |
} |
} |
708 |
|
|
709 |
sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from |
sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from |
711 |
// render current audio fragment |
// render current audio fragment |
712 |
Synthesize(Samples, ptr, Delay); |
Synthesize(Samples, ptr, Delay); |
713 |
|
|
714 |
DiskStreamRef.pStream->IncrementReadPos(int(Pos) * pSample->Channels); |
const int iPos = (int) Pos; |
715 |
Pos -= int(Pos); |
const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read |
716 |
|
DiskStreamRef.pStream->IncrementReadPos(readSampleWords); |
717 |
|
Pos -= iPos; // just keep fractional part of Pos |
718 |
|
|
719 |
|
// change state of voice to 'end' if we really reached the end of the sample data |
720 |
|
if (DiskStreamRef.State == Stream::state_end && readSampleWords >= sampleWordsLeftToRead) this->PlaybackState = playback_state_end; |
721 |
} |
} |
722 |
break; |
break; |
723 |
|
|
936 |
float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0]; |
float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0]; |
937 |
float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0]; |
float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0]; |
938 |
FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); |
FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); |
939 |
|
FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); |
940 |
pEngine->pBasicFilterParameters[0] = bqbase; |
pEngine->pBasicFilterParameters[0] = bqbase; |
941 |
pEngine->pMainFilterParameters[0] = bqmain; |
pEngine->pMainFilterParameters[0] = bqmain; |
942 |
|
|
950 |
prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i]; |
prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i]; |
951 |
prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i]; |
prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i]; |
952 |
FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); |
FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); |
953 |
|
FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); |
954 |
} |
} |
955 |
} |
} |
956 |
|
|
957 |
//same as 'pEngine->pBasicFilterParameters[i] = bqbase;' |
//same as 'pEngine->pBasicFilterParameters[i] = bqbase;' |
958 |
bq = (float*) &pEngine->pBasicFilterParameters[i]; |
bq = (float*) &pEngine->pBasicFilterParameters[i]; |
959 |
bq[0] = bqbase.a1; |
bq[0] = bqbase.b0; |
960 |
bq[1] = bqbase.a2; |
bq[1] = bqbase.b1; |
961 |
bq[2] = bqbase.b0; |
bq[2] = bqbase.b2; |
962 |
bq[3] = bqbase.b1; |
bq[3] = bqbase.a1; |
963 |
bq[4] = bqbase.b2; |
bq[4] = bqbase.a2; |
964 |
|
|
965 |
// same as 'pEngine->pMainFilterParameters[i] = bqmain;' |
// same as 'pEngine->pMainFilterParameters[i] = bqmain;' |
966 |
bq = (float*) &pEngine->pMainFilterParameters[i]; |
bq = (float*) &pEngine->pMainFilterParameters[i]; |
967 |
bq[0] = bqmain.a1; |
bq[0] = bqmain.b0; |
968 |
bq[1] = bqmain.a2; |
bq[1] = bqmain.b1; |
969 |
bq[2] = bqmain.b0; |
bq[2] = bqmain.b2; |
970 |
bq[3] = bqmain.b1; |
bq[3] = bqmain.a1; |
971 |
bq[4] = bqmain.b2; |
bq[4] = bqmain.a2; |
972 |
} |
} |
973 |
} |
} |
974 |
|
|
980 |
* @param pSrc - pointer to input sample data |
* @param pSrc - pointer to input sample data |
981 |
* @param Skip - number of sample points to skip in output buffer |
* @param Skip - number of sample points to skip in output buffer |
982 |
*/ |
*/ |
983 |
void Voice::Synthesize(uint Samples, sample_t* pSrc, int Skip) { |
void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) { |
984 |
UpdateSynthesisMode(); |
RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip); |
|
SynthesizeFragment_Fn* f = (SynthesizeFragment_Fn*) SynthesizeFragmentFnPtr; |
|
|
f(*this, Samples, pSrc, Skip); |
|
|
} |
|
|
|
|
|
/** |
|
|
* Determine the respective synthesis function for the given synthesis |
|
|
* mode. |
|
|
*/ |
|
|
void Voice::UpdateSynthesisMode() { |
|
|
SynthesizeFragmentFnPtr = GetSynthesisFunction(SynthesisMode); |
|
985 |
} |
} |
986 |
|
|
987 |
/** |
/** |