예제 #1
0
void CTrack_DSP::Process(tint32 iSamples)
{
	if (mbIsBusOrMix == true) {
		mpBuffer->SetChannelsNoConvert(2);
	}
	else
		mpBuffer->SetChannelsNoConvert(1);
		
	if (mbIsBusOrMix == false) {
		mpBuffer->Clear();
	}

	// (mo) Note: Currently if 2 sounds overlap, the second will be played out of sync

	// We use this temporary copy, so we can change it in the loop
	tuint64 uiSongPosTemp = muiSongPos;
	tuint64 iSamplesLeft = iSamples;
	tuint64 iBufferIndex = 0;
	while (mitRegionsInfo != mRegionInfoList.end() &&
			iSamplesLeft) {
		// Still region(s) to play
		CRegion_DSP* pRegion = (*mitRegionsInfo)->pRegion;
		tuint64 uiPosStart = (*mitRegionsInfo)->uiTrack_Pos;
		tuint64 uiPosEnd = uiPosStart + pRegion->Get_Duration() - 1;

		tint32 iChannels = pRegion->GetChannels();
		mpBuffer->SetChannels(iChannels);

		if (uiPosStart <= uiSongPosTemp) {
			if (uiPosEnd >= uiSongPosTemp) {
				tint32 iSamplesToGet = (tint32)(uiPosEnd - uiPosStart + 1);
				if (iSamplesToGet > iSamplesLeft) {
					iSamplesToGet = (tint32)iSamplesLeft;
				}
				if (iSamplesToGet > uiPosEnd - uiSongPosTemp + 1) {
					iSamplesToGet = (tint32)(uiPosEnd - uiSongPosTemp + 1);
				}

				if (iChannels == 1) {
					tfloat32* pfData = mpBuffer->GetData(0);
					tfloat32* ppfData[1];
					ppfData[0] = pfData + iBufferIndex;
					pRegion->GetSamples(ppfData, iSamplesToGet);
					if (mbLimitDataFromStream) {
						// Maybe silence some samples at start and/or end of portion

						// Silence at start?
						tint64 iSilentSamples_Start = miFirstStreamIx_Limited - uiSongPosTemp;
						if (iSilentSamples_Start > 0) {
							// We need to silence some samples at start of portion
							if (iSilentSamples_Start > iSamplesToGet) {
								iSilentSamples_Start = iSamplesToGet;
							}
							mpDSPTools->Clear(ppfData[0], iSilentSamples_Start);
						}

						// Silence at end?
						tint64 iSilentSamples_EndIx = miFinalStreamIx_Limited - uiSongPosTemp;
						if (iSilentSamples_EndIx < iSamplesToGet) {
							// We need to silence some samples at end of portion
							if (iSilentSamples_EndIx < 0) {
								iSilentSamples_EndIx = 0;
							}
							tint32 iSamplesToSilence = iSamplesToGet - iSilentSamples_EndIx;
							tfloat32* pf0Ix = ((tfloat32*)ppfData[0]) + iSilentSamples_EndIx;
							mpDSPTools->Clear(pf0Ix, iSamplesToSilence);
						}
					}
				}
				else {
					tfloat32* pfData1 = mpBuffer->GetData(0);
					tfloat32* pfData2 = mpBuffer->GetData(1);
					tfloat32* ppfData[2];
					ppfData[0] = pfData1 + iBufferIndex;
					ppfData[1] = pfData2 + iBufferIndex;
					pRegion->GetSamples(ppfData, iSamplesToGet);
					if (mbLimitDataFromStream) {
						// Maybe silence some samples at start and/or end of portion

						// Silence at start?
						tint64 iSilentSamples_Start = miFirstStreamIx_Limited - uiSongPosTemp;
						if (iSilentSamples_Start > 0) {
							// We need to silence some samples at start of portion
							if (iSilentSamples_Start > iSamplesToGet) {
								iSilentSamples_Start = iSamplesToGet;
							}
							mpDSPTools->Clear(ppfData[0], iSilentSamples_Start);
							mpDSPTools->Clear(ppfData[1], iSilentSamples_Start);
						}

						// Silence at end?
						tint64 iSilentSamples_EndIx = miFinalStreamIx_Limited - uiSongPosTemp;
						if (iSilentSamples_EndIx < iSamplesToGet) {
							// We need to silence some samples at end of portion
							if (iSilentSamples_EndIx < 0) {
								iSilentSamples_EndIx = 0;
							}
							tint32 iSamplesToSilence = iSamplesToGet - iSilentSamples_EndIx;
							tfloat32* pf0Ix = ((tfloat32*)ppfData[0]) + iSilentSamples_EndIx;
							tfloat32* pf1Ix = ((tfloat32*)ppfData[1]) + iSilentSamples_EndIx;
							mpDSPTools->Clear(pf0Ix, iSamplesToSilence);
							mpDSPTools->Clear(pf1Ix, iSamplesToSilence);
						}
					}
				}

				iSamplesLeft -= iSamplesToGet;
				uiSongPosTemp += iSamplesToGet;
				iBufferIndex += iSamplesToGet;
			}
			else {
				// Skip to next region
				mitRegionsInfo++;

				if (mitRegionsInfo != mRegionInfoList.end()) {
					(*mitRegionsInfo)->pRegion->SetPos(0);

					if ((*mitRegionsInfo)->pRegion->GetChannels() > iChannels) {
						iChannels = (*mitRegionsInfo)->pRegion->GetChannels();
					}
				}
			}
		}
		else {
			// Region not started yet
			tuint64 uiSamplesToClear = uiPosStart - uiSongPosTemp;
			if (uiSamplesToClear > iSamplesLeft) {
				uiSamplesToClear = iSamplesLeft;
			}

			tfloat32* pfData = mpBuffer->GetData(0);
			mpDSPTools->Clear(pfData + iBufferIndex, (tuint32)uiSamplesToClear);

			iSamplesLeft -= (tuint32)uiSamplesToClear;
			uiSongPosTemp += (tuint32)uiSamplesToClear;
			iBufferIndex += (tuint32)uiSamplesToClear;
		}
	}

/*	mpBuffer->SetChannels(2);
	muiSongPos += iSamples;
	return;*/

	if (mbArmed) {
		tint32 iInputChannel = miInputChannel;

		// (lasse) Huh? What's this for?
		tint32 iChannels = 1;
		if (miInputChannel >= 1000) {
			iChannels = 2;
			iInputChannel -= 1000;
		}

		mpBuffer->SetChannels(iChannels);

		mpDSP->GetInput(mpBuffer, iChannels, iInputChannel, iSamples);

		if (miRecordingChannels == -1) {
			// (lasse) This is a HACK - need a way to determine
			miRecordingChannels = 2;//iChannels;
			// .. (lasse)

			iChannels = miRecordingChannels;
		}

		if (mpFileRecording) {
			SetInputChannelCount(miRecordingChannels);
			SetTrackMode(miRecordingChannels);

			if (miRecordingChannels == 1) {
				tfloat32* pf = mpBuffer->GetData(0);
				for (tint32 iPeak = iSamples; iPeak > 0; iPeak--) {
					tfloat32 f = fabs(*pf++);
					if (f > mfPeak)	mfPeak = f;
				}
				mpFileRecording->Write((const tchar*)mpBuffer->GetData(0), iSamples * sizeof(tfloat32));
			}
			else {
				tfloat32* pfL = mpBuffer->GetData(0);
				tfloat32* pfR = mpBuffer->GetData(1);
				for (tint32 iPeak = iSamples; iPeak > 0; iPeak--) {
					tfloat32 fL = *pfL++;
					tfloat32 fR = *pfR++;
					tfloat32 fMono = fL + fR;
					fL = fabs(fL);
					fR = fabs(fR);
					fMono = fabs(fMono);
					if (fL > mfPeak)		mfPeak = fL;
					if (fR > mfPeak)		mfPeak = fR;
					if (fMono > mfPeakMono)	mfPeakMono = fMono;
				}
				mpFileRecording->Write((const tchar*)mpBuffer->GetData(0), iSamples * sizeof(tfloat32));
				mpFileRecording->Write((const tchar*)mpBuffer->GetData(1), iSamples * sizeof(tfloat32));
			}
		}
	}

	// Tell the buffer how many channels it has from outset
	mpBuffer->SetChannels(miInputChannelCount);

	// If the bus mode has more channels than the raw input we haven't done the up-mix yet - do it now
	if (miModeChannelCount > miInputChannelCount) {
		// Mix up
		mpBuffer->SetChannels(miModeChannelCount);
	}

	// Apply effects
	tint32 iInsert;
	for (iInsert = 0; iInsert < giNumber_Of_Inserts; iInsert++) {
		if (mppInsert[iInsert] && mpbInsertBypass[iInsert] == false) {
			tfloat32* ppfBuffersOut[2];
			ppfBuffersOut[0] = mpfBufferTmp1;
			ppfBuffersOut[1] = mpfBufferTmp2;
			tfloat32* pfData1 = mpBuffer->GetData(0);
			tfloat32* pfData2 = mpBuffer->GetData(1);
			tfloat* ppfData[2];
			ppfData[0] = pfData1;
			ppfData[1] = pfData2;
			mppInsert[iInsert]->ProcessNonInPlace(ppfBuffersOut, (const tfloat**)ppfData, iSamples);
			memcpy(pfData1, ppfBuffersOut[0], iSamples * sizeof(tfloat32));
			memcpy(pfData2, ppfBuffersOut[1], iSamples * sizeof(tfloat32));
		}
	}

	// Prepare for panning
	mpBuffer->SetChannels(miNumberOfChannelsForPanner);
	
	// Apply out amp
	for (tuint iChannel=0; iChannel<mpBuffer->GetChannels(); iChannel++) {
		CBaseDezipper2* pDezipper = mapDezipperOutAmp[iChannel];
			
		//tfloat32 fTest, fPeak;
			
		//tint32 iSamplesAlign8 = (iSamples % 8) * 8;
		tfloat32* pfData = mpBuffer->GetData(iChannel);
		//tfloat32* pfDataStop = pfData + iSamples;
		//tfloat32* pfDataStopAlign8 = pfData + iSamplesAlign8;
			
		if (pDezipper->IsDezipNeeded()) {
			// Out-amp is changing - do a de-zip
			tfloat afDezip[1024];
			pDezipper->DezipSamples(afDezip, iSamples, 44100);
			tfloat32* pfMul = afDezip;
				
			// Don't keep old peaks (if there) when amp is changing
			mbKillDecay = true;
				
			mpDSPTools->Mul(pfData, pfMul, iSamples);
			/*
			// Apply and collect 8 aligned
			while (pfData < pfDataStopAlign8) {
				// Apply amp and collect meter value
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//1
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//2
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//3
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//4
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//5
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//6
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//7
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//8
			}
				
			// Apply and collect remainder
			while (pfData < pfDataStop) {
				// Apply amp and collect meter value
				fTest = *pfData++ *= *pfMul++;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//1
			}
			*/
		}
		else {
			// Out-amp factor is the same for all samples - just multiply
			tfloat fOutAmp = pDezipper->GetCurrent();
				
			// Keep old peaks (if not yet read) because amp isn't changing
			//fPeak = mafPeakVolumes[iChannel];
				
			if ((fOutAmp < 0.99999) || (fOutAmp > 1.00001)) {

				mpDSPTools->Mul(pfData, fOutAmp, iSamples);
				/*
				// Apply and collect 8 aligned
				while (pfData < pfDataStopAlign8) {
					// Apply amp and collect meter value
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//1
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//2
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//3
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//4
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//5
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//6
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//7
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//8
				}
				
				// Apply and collect remainder
				while (pfData < pfDataStop) {
					// Apply amp and collect meter value
					fTest = *pfData++ *= fOutAmp;		fTest = fabsf(fTest);		if (fTest > fPeak) fPeak = fTest;	//1
				}
				 */
			}
			else {
				/*
				// No output amplification - just collect meter values
										
				// Collect alligned to 8
				while (pfData < pfDataStopAlign8) {
					// Collect meter value
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//1
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//2
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//3
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//4
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//5
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//6
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//7
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//8
				}

				// Collect any remainder
				while (pfData < pfDataStop) {
					// Collect meter value
					fTest = fabsf(*pfData++);		if (fTest > fPeak) fPeak = fTest;	//1
				}
				*/
			}
		}
			
		//mafPeakVolumes[iChannel] = fPeak;
	}

	tint32 iAUX;
	for (iAUX = 0; iAUX < 2; iAUX++) {
		if (mpfAUXVolume[iAUX] != 0) {
			CBuffer* pBufferAUX = mppAUXes[iAUX]->GetBuffer();

//			*pBufferAUX += *mpBuffer;
			pBufferAUX->Accumulate(*mpBuffer, mpfAUXVolume[iAUX]);
		}
	}

	// Maybe do down or up mix for destination
	mpBuffer->SetChannels(miDestinationNumberOfChannels);

	muiSongPos += iSamples;
} // Process