sampleCount Mixer::Process(int maxToProcess) { if (mT >= mT1) return 0; int i, j; sampleCount out; sampleCount maxOut = 0; int *channelFlags = new int[mNumChannels]; mMaxOut = maxToProcess; Clear(); for(i=0; i<mNumInputTracks; i++) { WaveTrack *track = mInputTrack[i]; for(j=0; j<mNumChannels; j++) channelFlags[j] = 0; switch(track->GetChannel()) { case Track::MonoChannel: default: for(j=0; j<mNumChannels; j++) channelFlags[j] = 1; break; case Track::LeftChannel: channelFlags[0] = 1; break; case Track::RightChannel: if (mNumChannels >= 2) channelFlags[1] = 1; else channelFlags[0] = 1; break; } if (mTimeTrack || track->GetRate() != mRate) out = MixVariableRates(channelFlags, track, &mSamplePos[i], mSampleQueue[i], &mQueueStart[i], &mQueueLen[i], mSRC[i]); else out = MixSameRate(channelFlags, track, &mSamplePos[i]); if (out > maxOut) maxOut = out; } mT += (maxOut / mRate); delete [] channelFlags; return maxOut; }
bool EffectTwoPassSimpleMono::ProcessPass() { //Iterate over each track SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks); WaveTrack *track = (WaveTrack *) iter.First(); mCurTrackNum = 0; while (track) { //Get start and end times from track double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); //Set the current bounds to whichever left marker is //greater and whichever right marker is less: mCurT0 = mT0 < trackStart? trackStart: mT0; mCurT1 = mT1 > trackEnd? trackEnd: mT1; // Process only if the right marker is to the right of the left marker if (mCurT1 > mCurT0) { //Transform the marker timepoints to samples sampleCount start = track->TimeToLongSamples(mCurT0); sampleCount end = track->TimeToLongSamples(mCurT1); //Get the track rate and samples mCurRate = track->GetRate(); mCurChannel = track->GetChannel(); //NewTrackPass1/2() returns true by default bool ret; if (mPass == 0) ret = NewTrackPass1(); else ret = NewTrackPass2(); if (!ret) return false; //ProcessOne() (implemented below) processes a single track if (!ProcessOne(track, start, end)) return false; } //Iterate to the next track track = (WaveTrack *) iter.Next(); mCurTrackNum++; } return true; }
bool EffectSimpleMono::Process() { //Iterate over each track this->CopyInputWaveTracks(); // Set up mOutputWaveTracks. bool bGoodResult = true; TrackListIterator iter(mOutputWaveTracks); WaveTrack* pOutWaveTrack = (WaveTrack*)(iter.First()); mCurTrackNum = 0; while (pOutWaveTrack != NULL) { //Get start and end times from track double trackStart = pOutWaveTrack->GetStartTime(); double trackEnd = pOutWaveTrack->GetEndTime(); //Set the current bounds to whichever left marker is //greater and whichever right marker is less: mCurT0 = mT0 < trackStart? trackStart: mT0; mCurT1 = mT1 > trackEnd? trackEnd: mT1; // Process only if the right marker is to the right of the left marker if (mCurT1 > mCurT0) { //Transform the marker timepoints to samples longSampleCount start = pOutWaveTrack->TimeToLongSamples(mCurT0); longSampleCount end = pOutWaveTrack->TimeToLongSamples(mCurT1); //Get the track rate and samples mCurRate = pOutWaveTrack->GetRate(); mCurChannel = pOutWaveTrack->GetChannel(); //NewTrackSimpleMono() will returns true by default //ProcessOne() processes a single track if (!NewTrackSimpleMono() || !ProcessOne(pOutWaveTrack, start, end)) { bGoodResult = false; break; } } //Iterate to the next track pOutWaveTrack = (WaveTrack*)(iter.Next()); mCurTrackNum++; } this->ReplaceProcessedWaveTracks(bGoodResult); return bGoodResult; }
bool EffectSoundTouch::Process() { //Assumes that mSoundTouch has already been initialized //by the subclass //Iterate over each track TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *) iter.First(); mCurTrackNum = 0; m_maxNewLength = 0.0; while (track) { //Get start and end times from track double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); //Set the current bounds to whichever left marker is //greater and whichever right marker is less: mCurT0 = mT0 < trackStart? trackStart: mT0; mCurT1 = mT1 > trackEnd? trackEnd: mT1; // Process only if the right marker is to the right of the left marker if (mCurT1 > mCurT0) { //Transform the marker timepoints to samples longSampleCount start = track->TimeToLongSamples(mCurT0); longSampleCount end = track->TimeToLongSamples(mCurT1); //Get the track rate and samples mCurRate = track->GetRate(); mCurChannel = track->GetChannel(); //ProcessOne() (implemented below) processes a single track if (!ProcessOne(track, start, end)) return false; } //Iterate to the next track track = (WaveTrack *) iter.Next(); mCurTrackNum++; } delete mSoundTouch; mSoundTouch = NULL; mT1 = mT0 + m_maxNewLength; // Update selection. return true; }
sampleCount Mixer::Process(int maxToProcess) { if (mT >= mT1) return 0; int i, j; sampleCount out; sampleCount maxOut = 0; int *channelFlags = new int[mNumChannels]; mMaxOut = maxToProcess; Clear(); for(i=0; i<mNumInputTracks; i++) { WaveTrack *track = mInputTrack[i]; for(j=0; j<mNumChannels; j++) channelFlags[j] = 0; if( mMixerSpec ) { //ignore left and right when downmixing is not required for( j = 0; j < mNumChannels; j++ ) channelFlags[ j ] = mMixerSpec->mMap[ i ][ j ] ? 1 : 0; } else { switch(track->GetChannel()) { case Track::MonoChannel: default: for(j=0; j<mNumChannels; j++) channelFlags[j] = 1; break; case Track::LeftChannel: channelFlags[0] = 1; break; case Track::RightChannel: if (mNumChannels >= 2) channelFlags[1] = 1; else channelFlags[0] = 1; break; } } if (mTimeTrack || track->GetRate() != mRate) out = MixVariableRates(channelFlags, track, &mSamplePos[i], mSampleQueue[i], &mQueueStart[i], &mQueueLen[i], mSRC[i]); else out = MixSameRate(channelFlags, track, &mSamplePos[i]); if (out > maxOut) maxOut = out; } out = mInterleaved ? maxOut * mNumChannels : maxOut; for(int c=0; c<mNumBuffers; c++) CopySamples(mTemp[c], floatSample, mBuffer[c], mFormat, out); mT += (maxOut / mRate); delete [] channelFlags; return maxOut; }
sampleCount Mixer::Process(sampleCount maxToProcess) { // MB: this is wrong! mT represented warped time, and mTime is too inaccurate to use // it here. It's also unnecessary I think. //if (mT >= mT1) // return 0; int i, j; sampleCount maxOut = 0; int *channelFlags = new int[mNumChannels]; mMaxOut = maxToProcess; Clear(); for(i=0; i<mNumInputTracks; i++) { WaveTrack *track = mInputTrack[i]; for(j=0; j<mNumChannels; j++) channelFlags[j] = 0; if( mMixerSpec ) { //ignore left and right when downmixing is not required for( j = 0; j < mNumChannels; j++ ) channelFlags[ j ] = mMixerSpec->mMap[ i ][ j ] ? 1 : 0; } else { switch(track->GetChannel()) { case Track::MonoChannel: default: for(j=0; j<mNumChannels; j++) channelFlags[j] = 1; break; case Track::LeftChannel: channelFlags[0] = 1; break; case Track::RightChannel: if (mNumChannels >= 2) channelFlags[1] = 1; else channelFlags[0] = 1; break; } } if (mbVariableRates || track->GetRate() != mRate) maxOut = std::max(maxOut, MixVariableRates(channelFlags, track, &mSamplePos[i], mSampleQueue[i], &mQueueStart[i], &mQueueLen[i], mResample[i])); else maxOut = std::max(maxOut, MixSameRate(channelFlags, track, &mSamplePos[i])); double t = (double)mSamplePos[i] / (double)track->GetRate(); if (mT0 > mT1) // backwards (as possibly in scrubbing) mTime = std::max(std::min(t, mTime), mT1); else // forwards (the usual) mTime = std::min(std::max(t, mTime), mT1); } if(mInterleaved) { for(int c=0; c<mNumChannels; c++) { CopySamples(mTemp[0] + (c * SAMPLE_SIZE(floatSample)), floatSample, mBuffer[0] + (c * SAMPLE_SIZE(mFormat)), mFormat, maxOut, mHighQuality, mNumChannels, mNumChannels); } } else { for(int c=0; c<mNumBuffers; c++) { CopySamples(mTemp[c], floatSample, mBuffer[c], mFormat, maxOut, mHighQuality); } } // MB: this doesn't take warping into account, replaced with code based on mSamplePos //mT += (maxOut / mRate); delete [] channelFlags; return maxOut; }
bool EffectNormalize::Process() { bool wasLinked = false; // set when a track has a linked (stereo) track if (mGain == false && mDC == false) return true; //Iterate over each track this->CopyInputTracks(); // Set up mOutputTracks. bool bGoodResult = true; SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks); WaveTrack *track = (WaveTrack *) iter.First(); mCurTrackNum = 0; while (track) { //Get start and end times from track double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); //Set the current bounds to whichever left marker is //greater and whichever right marker is less: mCurT0 = mT0 < trackStart? trackStart: mT0; mCurT1 = mT1 > trackEnd? trackEnd: mT1; // Process only if the right marker is to the right of the left marker if (mCurT1 > mCurT0) { //Transform the marker timepoints to samples sampleCount start = track->TimeToLongSamples(mCurT0); sampleCount end = track->TimeToLongSamples(mCurT1); //Get the track rate and samples mCurRate = track->GetRate(); mCurChannel = track->GetChannel(); if(mStereoInd) // do stereo tracks independently (the easy way) track->GetMinMax(&mMin, &mMax, mCurT0, mCurT1); else { if(!wasLinked) // new mono track or first of a stereo pair { track->GetMinMax(&mMin, &mMax, mCurT0, mCurT1); if(track->GetLinked()) { wasLinked = true; // so we use these values for the next (linked) track track = (WaveTrack *) iter.Next(); // get the next one for the max/min float min, max; track->GetMinMax(&min, &max, mCurT0, mCurT1); mMin = min < mMin ? min : mMin; mMax = max > mMax ? max : mMax; track = (WaveTrack *) iter.Prev(); // back to the one we are on } } else wasLinked = false; // second of the stereo pair, next one is mono or first } //ProcessOne() (implemented below) processes a single track if (!ProcessOne(track, start, end)) { bGoodResult = false; break; } } //Iterate to the next track track = (WaveTrack *) iter.Next(); mCurTrackNum++; } this->ReplaceProcessedTracks(bGoodResult); return bGoodResult; }
void AudioIO::FillBuffers() { unsigned int numEmpty = 0; unsigned int i; // Playback buffers for(i=0; i<mNumOutBuffers; i++) { if (mOutBuffer[i].ID == 0) numEmpty++; } if (numEmpty > (mNumOutBuffers/2)) { sampleCount block = numEmpty * mBufferSize; double deltat = block / mRate; if (mT + deltat > mT1) { deltat = mT1 - mT; if(deltat < 0.0) return; block = (sampleCount)(deltat * mRate + 0.5); } Mixer *mixer = new Mixer(mNumOutChannels, block, true, mRate, mFormat); mixer->UseVolumeSlider(mProject->GetControlToolBar()); mixer->Clear(); TrackListIterator iter2(mTracks); int numSolo = 0; Track *vt = iter2.First(); while (vt) { if (vt->GetKind() == Track::Wave && vt->GetSolo()) numSolo++; vt = iter2.Next(); } TrackListIterator iter(mTracks); vt = iter.First(); while (vt) { if (vt->GetKind() == Track::Wave) { Track *mt = vt; // We want to extract mute and solo information from // the top of the two tracks if they're linked // (i.e. a stereo pair only has one set of mute/solo buttons) Track *partner = mTracks->GetLink(vt); if (partner && !vt->GetLinked()) mt = partner; else mt = vt; // Cut if somebody else is soloing if (numSolo>0 && !mt->GetSolo()) { vt = iter.Next(); continue; } // Cut if we're muted (unless we're soloing) if (mt->GetMute() && !mt->GetSolo()) { vt = iter.Next(); continue; } WaveTrack *t = (WaveTrack *) vt; switch (t->GetChannel()) { case Track::LeftChannel: mixer->MixLeft(t, mT, mT + deltat); break; case Track::RightChannel: mixer->MixRight(t, mT, mT + deltat); break; case Track::MonoChannel: mixer->MixMono(t, mT, mT + deltat); break; } } vt = iter.Next(); } // Copy the mixed samples into the buffers samplePtr outbytes = mixer->GetBuffer(); for(i=0; i<mNumOutBuffers && block>0; i++) if (mOutBuffer[i].ID == 0) { sampleCount count; if (block > mBufferSize) count = mBufferSize; else count = block; memcpy(mOutBuffer[i].data, outbytes, count*mNumOutChannels*SAMPLE_SIZE(mFormat)); block -= count; outbytes += (count*mNumOutChannels*SAMPLE_SIZE(mFormat)); mOutBuffer[i].len = count; mOutBuffer[i].ID = mOutID; mOutID++; } delete mixer; mT += deltat; } // Recording buffers unsigned int numFull = 0; unsigned int f, c; // loop counters sampleCount flatLen; for(i=0; i<mNumInBuffers; i++) { if (mInBuffer[i].ID != 0) numFull++; } if (numFull > 8) { samplePtr *flat = new samplePtr[mNumInChannels]; for(i=0; i<mNumInChannels; i++) flat[i] = NewSamples(numFull * mBufferSize, mFormat); flatLen = 0; for(f=0; f<numFull; f++) { int minID = mInID+1; int minIndex = 0; for(i=0; i<mNumInBuffers; i++) if (mInBuffer[i].ID > 0 && mInBuffer[i].ID < minID) { minIndex = i; minID = mInBuffer[i].ID; } switch(mFormat) { case floatSample: int j; for(j=0; j<mInBuffer[minIndex].len; j++) for(c=0; c<mNumInChannels; c++) { ((float *)flat[c])[flatLen+j] = ((float *)mInBuffer[minIndex].data)[j*mNumInChannels + c]; } break; default: wxASSERT(0); } flatLen += mInBuffer[minIndex].len; mInBuffer[minIndex].ID = 0; } for(i=0; i<mNumInChannels; i++) mInTracks[i]->Append(flat[i], mFormat, flatLen); for(i=0; i<mNumInChannels; i++) DeleteSamples(flat[i]); delete[] flat; mProject->RedrawProject(); } }