bool EffectCompressor::InitPass1() { mMax=0.0; if (!mNormalize) DisableSecondPass(); // Find the maximum block length required for any track size_t maxlen = 0; SelectedTrackListOfKindIterator iter(Track::Wave, mTracks); WaveTrack *track = (WaveTrack *) iter.First(); while (track) { maxlen = std::max(maxlen, track->GetMaxBlockSize()); //Iterate to the next track track = (WaveTrack *) iter.Next(); } if(mFollow1!=NULL) { delete[] mFollow1; mFollow1 = NULL; } if(mFollow2!=NULL) { delete[] mFollow2; mFollow2 = NULL; } // Allocate buffers for the envelope if(maxlen > 0) { mFollow1 = new float[maxlen]; mFollow2 = new float[maxlen]; } mFollowLen = maxlen; return true; }
bool WaveTrack::Cut(double t0, double t1, Track **dest) { bool success; sampleCount s0, s1; WaveTrack *newTrack; if (t1 < t0) return false; TimeToSamplesClip(t0, &s0); TimeToSamplesClip(t1, &s1); newTrack = new WaveTrack(mDirManager); delete newTrack->mSequence; newTrack->mSequence = NULL; success = mSequence->Copy(s0, s1, &newTrack->mSequence); if (success) success = mSequence->Delete(s0, s1-s0); if (!success) { *dest = NULL; delete newTrack; return false; } newTrack->GetEnvelope()->CopyFrom(GetEnvelope(), t0, t1); mEnvelope->CollapseRegion(t0, t1); *dest = newTrack; MarkChanged(); return true; }
//This might continue over a number of blocks. double VoiceKey::TestEnergy (WaveTrack & t, sampleCount start, sampleCount len) { double sum = 1; auto s = start; //Keep track of start auto originalLen = len; //Keep track of the length of block to process (its not the length of t) const auto blockSize = limitSampleBufferSize( t.GetMaxBlockSize(), len); //Determine size of sampling buffer float *buffer = new float[blockSize]; //Get a sampling buffer while(len > 0) { //Figure out how much to grab auto block = limitSampleBufferSize ( t.GetBestBlockSize(s), len ); t.Get((samplePtr)buffer,floatSample, s,block); //grab the block; //Now, go through the block and calculate energy for(decltype(block) i = 0; i< block; i++) { sum += buffer[i]*buffer[i]; } len -= block; s += block; } delete [] buffer; return sum / originalLen.as_double(); }
bool EffectClickRemoval::Process() { this->CopyInputTracks(); // Set up mOutputTracks. bool bGoodResult = true; SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks); WaveTrack *track = (WaveTrack *) iter.First(); int count = 0; while (track) { double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); double t0 = mT0 < trackStart? trackStart: mT0; double t1 = mT1 > trackEnd? trackEnd: mT1; if (t1 > t0) { sampleCount start = track->TimeToLongSamples(t0); sampleCount end = track->TimeToLongSamples(t1); sampleCount len = (sampleCount)(end - start); if (!ProcessOne(count, track, start, len)) { bGoodResult = false; break; } } track = (WaveTrack *) iter.Next(); count++; } this->ReplaceProcessedTracks(bGoodResult); return bGoodResult; }
bool EffectPaulstretch::Process() { CopyInputTracks(); SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks.get()); WaveTrack *track = (WaveTrack *) iter.First(); m_t1=mT1; int count=0; while (track) { double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); double t0 = mT0 < trackStart? trackStart: mT0; double t1 = mT1 > trackEnd? trackEnd: mT1; if (t1 > t0) { if (!ProcessOne(track, t0,t1,count)) return false; } track = (WaveTrack *) iter.Next(); count++; } mT1=m_t1; ReplaceProcessedTracks(true); return true; }
bool WaveTrack::Copy(double t0, double t1, Track **dest) { if (t1 < t0) return false; sampleCount s0, s1; TimeToSamplesClip(t0, &s0); TimeToSamplesClip(t1, &s1); WaveTrack *newTrack = new WaveTrack(mDirManager); newTrack->Init(*this); delete newTrack->mSequence; newTrack->mSequence = NULL; if (!mSequence->Copy(s0, s1, &newTrack->mSequence)) { // Error *dest = NULL; delete newTrack; return false; } newTrack->GetEnvelope()->CopyFrom(GetEnvelope(), t0, t1); *dest = newTrack; MarkChanged(); return true; }
void AudioPrefetch::prefetch(bool doSeek) { if (writePos == ~0U) { printf("AudioPrefetch::prefetch: invalid write position\n"); return; } if (MusEGlobal::song->loop() && !MusEGlobal::audio->bounce() && !MusEGlobal::extSyncFlag.value()) { const Pos& loop = MusEGlobal::song->rPos(); unsigned n = loop.frame() - writePos; if (n < MusEGlobal::segmentSize) { unsigned lpos = MusEGlobal::song->lPos().frame(); // adjust loop start so we get exact loop len if (n > lpos) n = 0; writePos = lpos - n; } } WaveTrackList* tl = MusEGlobal::song->waves(); for (iWaveTrack it = tl->begin(); it != tl->end(); ++it) { WaveTrack* track = *it; // Save time. Don't bother if track is off. Track On/Off not designed for rapid repeated response (but mute is). (p3.3.29) if(track->off()) continue; int ch = track->channels(); float* bp[ch]; if (track->prefetchFifo()->getWriteBuffer(ch, MusEGlobal::segmentSize, bp, writePos)) continue; track->fetchData(writePos, MusEGlobal::segmentSize, bp, doSeek); } writePos += MusEGlobal::segmentSize; }
bool EffectScienFilter::Init() { int selcount = 0; double rate = 0.0; TrackListOfKindIterator iter(Track::Wave, inputTracks()); WaveTrack *t = (WaveTrack *) iter.First(); mNyquist = (t ? t->GetRate() : GetActiveProject()->GetRate()) / 2.0; while (t) { if (t->GetSelected()) { if (selcount == 0) { rate = t->GetRate(); } else { if (t->GetRate() != rate) { Effect::MessageBox(_("To apply a filter, all selected tracks must have the same sample rate.")); return false; } } selcount++; } t = (WaveTrack *) iter.Next(); } return true; }
bool EffectCompressor::InitPass1() { mMax=0.0; if (!mNormalize) DisableSecondPass(); // Find the maximum block length required for any track size_t maxlen = 0; SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks()); WaveTrack *track = (WaveTrack *) iter.First(); while (track) { maxlen = std::max(maxlen, track->GetMaxBlockSize()); //Iterate to the next track track = (WaveTrack *) iter.Next(); } mFollow1.reset(); mFollow2.reset(); // Allocate buffers for the envelope if(maxlen > 0) { mFollow1.reinit(maxlen); mFollow2.reinit(maxlen); } mFollowLen = maxlen; return true; }
bool EffectEqualization::Process() { TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *) iter.First(); int count = 0; while (track) { double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); double t0 = mT0 < trackStart? trackStart: mT0; double t1 = mT1 > trackEnd? trackEnd: mT1; if (t1 > t0) { longSampleCount start = track->TimeToLongSamples(t0); longSampleCount end = track->TimeToLongSamples(t1); sampleCount len = (sampleCount)(end - start); if (!ProcessOne(count, track, start, len)) return false; } track = (WaveTrack *) iter.Next(); count++; } return true; }
//This might continue over a number of blocks. double VoiceKey::TestEnergy (WaveTrack & t, sampleCount start, sampleCount len) { double sum = 1; sampleCount s = start; //Keep track of start sampleCount originalLen = len; //Keep track of the length of block to process (its not the length of t) sampleCount blockSize = t.GetMaxBlockSize(); //Determine size of sampling buffer if( blockSize > len) blockSize = len; float *buffer = new float[blockSize]; //Get a sampling buffer while(len > 0) { sampleCount block = t.GetBestBlockSize(s); //Figure out how much to grab if(block > len) block = len; //Don't grab too much! t.Get((samplePtr)buffer,floatSample, s,block); //grab the block; //Now, go through the block and calculate energy for(int i = 0; i< block; i++) { sum += buffer[i]*buffer[i]; } len -= block; s += block; } delete [] buffer; return sum / originalLen; }
// Deduce m_FromFrequency from the samples at the beginning of // the selection. Then set some other params accordingly. void EffectChangePitch::DeduceFrequencies() { // As a neat trick, attempt to get the frequency of the note at the // beginning of the selection. SelectedTrackListOfKindIterator iter(Track::Wave, inputTracks()); WaveTrack *track = (WaveTrack *) iter.First(); if (track) { double rate = track->GetRate(); // Auto-size window -- high sample rates require larger windowSize. // Aim for around 2048 samples at 44.1 kHz (good down to about 100 Hz). // To detect single notes, analysis period should be about 0.2 seconds. // windowSize must be a power of 2. const size_t windowSize = // windowSize < 256 too inaccurate std::max(256, wxRound(pow(2.0, floor((log(rate / 20.0)/log(2.0)) + 0.5)))); // we want about 0.2 seconds to catch the first note. // number of windows rounded to nearest integer >= 1. const unsigned numWindows = std::max(1, wxRound((double)(rate / (5.0f * windowSize)))); double trackStart = track->GetStartTime(); double t0 = mT0 < trackStart? trackStart: mT0; auto start = track->TimeToLongSamples(t0); auto analyzeSize = windowSize * numWindows; Floats buffer{ analyzeSize }; Floats freq{ windowSize / 2 }; Floats freqa{ windowSize / 2, true }; track->Get((samplePtr) buffer.get(), floatSample, start, analyzeSize); for(unsigned i = 0; i < numWindows; i++) { ComputeSpectrum(buffer.get() + i * windowSize, windowSize, windowSize, rate, freq.get(), true); for(size_t j = 0; j < windowSize / 2; j++) freqa[j] += freq[j]; } size_t argmax = 0; for(size_t j = 1; j < windowSize / 2; j++) if (freqa[j] > freqa[argmax]) argmax = j; auto lag = (windowSize / 2 - 1) - argmax; m_dStartFrequency = rate / lag; } double dFromMIDInote = FreqToMIDInote(m_dStartFrequency); double dToMIDInote = dFromMIDInote + m_dSemitonesChange; m_nFromPitch = PitchIndex(dFromMIDInote); m_nFromOctave = PitchOctave(dFromMIDInote); m_nToPitch = PitchIndex(dToMIDInote); m_nToOctave = PitchOctave(dToMIDInote); m_FromFrequency = m_dStartFrequency; Calc_PercentChange(); Calc_ToFrequency(); }
// get the sum of the sizes of all blocks this track list // references. However, if a block is referred to multiple // times it is only counted once. Return value is in bytes. wxLongLong UndoManager::CalculateSpaceUsage(int index) { TrackListOfKindIterator iter(Track::Wave); WaveTrack *wt; WaveClipList::compatibility_iterator it; BlockArray *blocks; unsigned int i; // get a map of all blocks referenced in this TrackList std::map<BlockFile*, wxLongLong> cur; wt = (WaveTrack *) iter.First(stack[index]->tracks); while (wt) { for (it = wt->GetClipIterator(); it; it = it->GetNext()) { blocks = it->GetData()->GetSequenceBlockArray(); for (i = 0; i < blocks->GetCount(); i++) { BlockFile* pBlockFile = blocks->Item(i)->f; if (pBlockFile->GetFileName().FileExists()) cur[pBlockFile] = pBlockFile->GetSpaceUsage(); } } wt = (WaveTrack *) iter.Next(); } if (index > 0) { // get a set of all blocks referenced in all prev TrackList std::set<BlockFile*> prev; while (--index) { wt = (WaveTrack *) iter.First(stack[index]->tracks); while (wt) { for (it = wt->GetClipIterator(); it; it = it->GetNext()) { blocks = it->GetData()->GetSequenceBlockArray(); for (i = 0; i < blocks->GetCount(); i++) { prev.insert(blocks->Item(i)->f); } } wt = (WaveTrack *) iter.Next(); } } // remove all blocks in prevBlockFiles from curBlockFiles std::set<BlockFile*>::const_iterator prevIter; for (prevIter = prev.begin(); prevIter != prev.end(); prevIter++) { cur.erase(*prevIter); } } // sum the sizes of the blocks remaining in curBlockFiles; wxLongLong bytes = 0; std::map<BlockFile*, wxLongLong>::const_iterator curIter; for (curIter = cur.begin(); curIter != cur.end(); curIter++) { bytes += curIter->second; } return bytes; }
void UndoManager::Debug() { for (unsigned int i = 0; i < stack.Count(); i++) { TrackListIterator iter(stack[i]->tracks); WaveTrack *t = (WaveTrack *) (iter.First()); printf("*%d* %s %f\n", i, (i == (unsigned int)current) ? "-->" : " ", t ? t->GetEndTime()-t->GetStartTime() : 0); } }
bool EffectNoiseRemoval::Process() { if (!mDoProfile && !mHasProfile) CleanSpeechMayReadNoisegate(); // If we still don't have a profile we have a problem. // This should only happen in CleanSpeech. if(!mDoProfile && !mHasProfile) { wxMessageBox( _("Attempt to run Noise Removal without a noise profile.\n")); return false; } Initialize(); // This same code will both remove noise and profile it, // depending on 'mDoProfile' this->CopyInputWaveTracks(); // Set up mOutputWaveTracks. bool bGoodResult = true; TrackListIterator iter(mOutputWaveTracks); WaveTrack *track = (WaveTrack *) iter.First(); int count = 0; while (track) { double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); double t0 = mT0 < trackStart? trackStart: mT0; double t1 = mT1 > trackEnd? trackEnd: mT1; if (t1 > t0) { sampleCount start = track->TimeToLongSamples(t0); sampleCount end = track->TimeToLongSamples(t1); sampleCount len = (sampleCount)(end - start); if (!ProcessOne(count, track, start, len)) { Cleanup(); bGoodResult = false; break; } } track = (WaveTrack *) iter.Next(); count++; } if (bGoodResult && mDoProfile) { CleanSpeechMayWriteNoiseGate(); mHasProfile = true; mDoProfile = false; } if (bGoodResult) Cleanup(); this->ReplaceProcessedWaveTracks(bGoodResult); return bGoodResult; }
bool EffectFindClipping::Process() { LabelTrack *l = NULL; Track *original = NULL; TrackListOfKindIterator iter(Track::Label, mTracks); for (Track *t = iter.First(); t; t = iter.Next()) { if (t->GetName() == wxT("Clipping")) { l = (LabelTrack *) t; // copy LabelTrack here, so it can be undone on cancel l->Copy(l->GetStartTime(), l->GetEndTime(), &original); original->SetOffset(l->GetStartTime()); original->SetName(wxT("Clipping")); break; } } if (!l) { l = mFactory->NewLabelTrack(); l->SetName(_("Clipping")); mTracks->Add((Track *) l); } int count = 0; // JC: Only process selected tracks. SelectedTrackListOfKindIterator waves(Track::Wave, mTracks); WaveTrack *t = (WaveTrack *) waves.First(); while (t) { double trackStart = t->GetStartTime(); double trackEnd = t->GetEndTime(); double t0 = mT0 < trackStart ? trackStart : mT0; double t1 = mT1 > trackEnd ? trackEnd : mT1; if (t1 > t0) { sampleCount start = t->TimeToLongSamples(t0); sampleCount end = t->TimeToLongSamples(t1); sampleCount len = (sampleCount)(end - start); if (!ProcessOne(l, count, t, start, len)) { //put it back how it was mTracks->Remove((Track *) l); if(original) { mTracks->Add((Track *) original); } return false; } } count++; t = (WaveTrack *) waves.Next(); } return true; }
void AudioPrefetch::seek(unsigned seekTo) { // printf("seek %d\n", seekTo); #ifdef AUDIOPREFETCH_DEBUG printf("AudioPrefetch::seek to:%u seekCount:%d\n", seekTo, seekCount); #endif // Speedup: More than one seek message pending? // Eat up seek messages until we get to the very LATEST one, // because all the rest which came before it are irrelevant now, // and processing them all was taking extreme time, especially with // resampling enabled. // In particular, when the user 'slides' the play cursor back and forth // there are MANY seek messages in the pipe, and with resampling enabled // it was taking minutes to finish seeking. If the user hit play during that time, // things were messed up (FIFO underruns, choppy intermittent sound etc). // Added by Tim. p3.3.20 if (seekCount > 1) { --seekCount; return; } writePos = seekTo; WaveTrackList* tl = song->waves(); for (iWaveTrack it = tl->begin(); it != tl->end(); ++it) { WaveTrack* track = *it; track->clearPrefetchFifo(); } bool isFirstPrefetch = true; for (unsigned int i = 0; i < (fifoLength) - 1; ++i)//prevent compiler warning: comparison of signed/unsigned { // Indicate do a seek command before read, but only on the first pass. // Changed by Tim. p3.3.17 //prefetch(); prefetch(isFirstPrefetch); isFirstPrefetch = false; // To help speed things up even more, check the count again. Return if more seek messages are pending. // Added by Tim. p3.3.20 if (seekCount > 1) { --seekCount; return; } } seekPos = seekTo; //seekDone = true; --seekCount; }
void AudacityProject::OnPlotSpectrum(wxCommandEvent & event) { int selcount = 0; WaveTrack *selt = NULL; TrackListIterator iter(mTracks); VTrack *t = iter.First(); while (t) { if (t->GetSelected()) selcount++; if (t->GetKind() == VTrack::Wave) selt = (WaveTrack *) t; t = iter.Next(); } if (selcount != 1) { wxMessageBox(_("Please select a single track first.\n")); return; } /* This shouldn't be possible, since the menu is grayed out. * But we'll check just in case it does happen, to prevent * the crash that would result. */ if (!selt) { wxMessageBox(_("Please select a track first.\n")); return; } sampleCount s0 = (sampleCount) ((mViewInfo.sel0 - selt->GetOffset()) * selt->GetRate()); sampleCount s1 = (sampleCount) ((mViewInfo.sel1 - selt->GetOffset()) * selt->GetRate()); sampleCount slen = s1 - s0; if (slen > 1048576) slen = 1048576; float *data = new float[slen]; sampleType *data_sample = new sampleType[slen]; if (s0 >= selt->GetNumSamples() || s0 + slen > selt->GetNumSamples()) { wxMessageBox(_("Not enough samples selected.\n")); delete[]data; delete[]data_sample; return; } selt->Get(data_sample, s0, slen); for (sampleCount i = 0; i < slen; i++) data[i] = data_sample[i] / 32767.; gFreqWindow->Plot(slen, data, selt->GetRate()); gFreqWindow->Show(true); gFreqWindow->Raise(); delete[]data; delete[]data_sample; }
void UndoManager::CalculateSpaceUsage() { TIMER_START( "CalculateSpaceUsage", space_calc ); TrackListOfKindIterator iter(Track::Wave); space.Clear(); space.Add(0, stack.GetCount()); Set s1, s2; Set *prev = &s1; Set *cur = &s2; for (size_t i = 0, cnt = stack.GetCount(); i < cnt; i++) { // Swap map pointers std::swap(cur, prev); // And clean out the NEW current map cur->clear(); // Scan all tracks at current level WaveTrack *wt = (WaveTrack *) iter.First(stack[i]->tracks); while (wt) { // Scan all clips within current track WaveClipList::compatibility_iterator it = wt->GetClipIterator(); while (it) { // Scan all blockfiles within current clip BlockArray *blocks = it->GetData()->GetSequenceBlockArray(); for (size_t b = 0, cnt = blocks->size(); b < cnt; b++) { BlockFile *file = (*blocks)[b].f; // Accumulate space used by the file if the file didn't exist // in the previous level if (prev->count(file) == 0 && cur->count(file) == 0) { space[i] += file->GetSpaceUsage().GetValue(); } // Add file to current set cur->insert(file); } it = it->GetNext(); } wt = (WaveTrack *) iter.Next(); } } TIMER_STOP( space_calc ); }
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; }
// Find out how much additional space was used to execute // this operation. // // Computed by getting a list of all blocks referenced by // *this* TrackList and removing all blocks referenced by // any previous TrackList. wxLongLong TrackList::GetAdditionalSpaceUsage(UndoStack *stack) { TrackListNode *p; // get a map of all blocks referenced in this TrackList std::map<BlockFile*,wxLongLong> curBlockFiles; for (p = head; p; p = p->next) { if (p->t->GetKind() == Track::Wave) { WaveTrack* track = ((WaveTrack*)p->t); for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); BlockArray *blocks = clip->GetSequenceBlockArray(); for (unsigned int i = 0; i < blocks->GetCount(); i++) curBlockFiles[blocks->Item(i)->f] = blocks->Item(i)->f->GetSpaceUsage(); } } } // get a set of all blocks referenced in all prev TrackList std::set<BlockFile*> prevBlockFiles; unsigned int undoStackIdx = 0; for (; undoStackIdx < stack->GetCount(); undoStackIdx++) { UndoStackElem *stackElem = stack->Item(undoStackIdx); if (stackElem->tracks == this) break; for (p = stackElem->tracks->head; p; p = p->next) { if (p->t->GetKind() == Track::Wave) { WaveTrack* track = ((WaveTrack*)p->t); for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext()) { WaveClip* clip = it->GetData(); BlockArray *blocks = clip->GetSequenceBlockArray(); for (unsigned int i = 0; i < blocks->GetCount(); i++) prevBlockFiles.insert(blocks->Item(i)->f); } } } } // remove all blocks in prevBlockFiles from curBlockFiles std::set<BlockFile*>::const_iterator prevIter = prevBlockFiles.begin(); for (; prevIter != prevBlockFiles.end(); prevIter++) curBlockFiles.erase(*prevIter); // sum the sizes of the blocks remaining in curBlockFiles; std::map<BlockFile*,wxLongLong>::const_iterator curBfIter = curBlockFiles.begin(); wxLongLong bytes = 0; for (;curBfIter != curBlockFiles.end(); curBfIter++) bytes += curBfIter->second; return bytes; }
//TODO: There are a lot of places where a track is being checked // to see if it is stereo. Consolidate these bool EffectStereoToMono::CheckWhetherSkipEffect() { TrackListIterator iter(mWaveTracks); WaveTrack *t = (WaveTrack*)iter.First(); while (t) { if (t->GetLinked()) { return false; } t = (WaveTrack *)iter.Next(); } return true; }
void FreqWindow::GetAudio() { int selcount = 0; int i; bool warning = false; //wxLogDebug(wxT("Entering FreqWindow::GetAudio()")); TrackListIterator iter(p->GetTracks()); Track *t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == Track::Wave) { WaveTrack *track = (WaveTrack *)t; if (selcount==0) { mRate = track->GetRate(); sampleCount start, end; start = track->TimeToLongSamples(p->mViewInfo.sel0); end = track->TimeToLongSamples(p->mViewInfo.sel1); mDataLen = (sampleCount)(end - start); if (mDataLen > 10485760) { warning = true; mDataLen = 10485760; } if (mBuffer) { delete [] mBuffer; } mBuffer = new float[mDataLen]; track->Get((samplePtr)mBuffer, floatSample, start, mDataLen); } else { if (track->GetRate() != mRate) { wxMessageBox(_("To plot the spectrum, all selected tracks must be the same sample rate.")); delete[] mBuffer; mBuffer = NULL; return; } sampleCount start; start = track->TimeToLongSamples(p->mViewInfo.sel0); float *buffer2 = new float[mDataLen]; track->Get((samplePtr)buffer2, floatSample, start, mDataLen); for(i=0; i<mDataLen; i++) mBuffer[i] += buffer2[i]; delete[] buffer2; } selcount++; } t = iter.Next(); } if (selcount == 0) return; if (warning) { wxString msg; msg.Printf(_("Too much audio was selected. Only the first %.1f seconds of audio will be analyzed."), (mDataLen / mRate)); //wxLogDebug(wxT("About to show length warning message")); wxMessageBox(msg); //wxLogDebug(wxT("Length warning message done")); } //wxLogDebug(wxT("Leaving FreqWindow::GetAudio()")); }
void AudacityProject::OnNewWaveTrack(wxCommandEvent & event) { WaveTrack *t = new WaveTrack(&mDirManager); SelectNone(); mTracks->Add(t); t->SetSelected(true); PushState(_("Created new audio track")); FixScrollbars(); mTrackPanel->Refresh(false); }
void FreqWindow::GetAudio() { mData.reset(); mDataLen = 0; int selcount = 0; bool warning = false; TrackListIterator iter(p->GetTracks()); Track *t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == Track::Wave) { WaveTrack *track = (WaveTrack *)t; if (selcount==0) { mRate = track->GetRate(); auto start = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t0()); auto end = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t1()); auto dataLen = end - start; if (dataLen > 10485760) { warning = true; mDataLen = 10485760; } else // dataLen is not more than 10 * 2 ^ 20 mDataLen = dataLen.as_size_t(); mData = Floats{ mDataLen }; // Don't allow throw for bad reads track->Get((samplePtr)mData.get(), floatSample, start, mDataLen, fillZero, false); } else { if (track->GetRate() != mRate) { AudacityMessageBox(_("To plot the spectrum, all selected tracks must be the same sample rate.")); mData.reset(); mDataLen = 0; return; } auto start = track->TimeToLongSamples(p->mViewInfo.selectedRegion.t0()); Floats buffer2{ mDataLen }; // Again, stop exceptions track->Get((samplePtr)buffer2.get(), floatSample, start, mDataLen, fillZero, false); for (size_t i = 0; i < mDataLen; i++) mData[i] += buffer2[i]; } selcount++; } t = iter.Next(); } if (selcount == 0) return; if (warning) { wxString msg; msg.Printf(_("Too much audio was selected. Only the first %.1f seconds of audio will be analyzed."), (mDataLen / mRate)); AudacityMessageBox(msg); } }
bool EffectChangeSpeed::Process() { // Similar to EffectSoundTouch::Process() //Iterate over each track this->CopyInputWaveTracks(); // Set up m_pOutputWaveTracks. bool bGoodResult = true; TrackListIterator iter(m_pOutputWaveTracks); WaveTrack* pOutWaveTrack = (WaveTrack*)(iter.First()); mCurTrackNum = 0; m_maxNewLength = 0.0; while (pOutWaveTrack != NULL) { //Get start and end times from track mCurT0 = pOutWaveTrack->GetStartTime(); mCurT1 = pOutWaveTrack->GetEndTime(); //Set the current bounds to whichever left marker is //greater and whichever right marker is less: mCurT0 = wxMax(mT0, mCurT0); mCurT1 = wxMin(mT1, mCurT1); // 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); //ProcessOne() (implemented below) processes a single track if (!ProcessOne(pOutWaveTrack, start, end)) { bGoodResult = false; break; } } //Iterate to the next track pOutWaveTrack = (WaveTrack*)(iter.Next()); mCurTrackNum++; } this->ReplaceProcessedWaveTracks(bGoodResult); // mT1 = mT0 + m_maxNewLength; // Update selection. return bGoodResult; }
bool EffectRepeat::PromptUser() { // // Figure out the maximum number of times the selection // could be repeated without overflowing any track // int maxCount = -1; TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *) iter.First(); while (track) { sampleCount trackLen = (sampleCount)((track->GetEndTime() - track->GetStartTime()) * track->GetRate()); sampleCount selectionLen = (sampleCount)((mT1 - mT0) * track->GetRate()); int availSamples = 2147483647 - trackLen; int count = availSamples / selectionLen; if (maxCount == -1 || count < maxCount) maxCount = count; track = (WaveTrack *) iter.Next(); } if (maxCount <= 1) { wxMessageBox(_("Tracks are too long to repeat the selection."), _("Repeat"), wxOK | wxCENTRE, mParent); return false; } RepeatDialog dlog(this, mParent); dlog.repeatCount = repeatCount; dlog.selectionTimeSecs = mT1 - mT0; dlog.maxCount = maxCount; dlog.TransferDataToWindow(); dlog.CentreOnParent(); dlog.ShowModal(); if (dlog.GetReturnCode() == wxID_CANCEL) return false; repeatCount = dlog.repeatCount; if (repeatCount > maxCount) repeatCount = maxCount; if (repeatCount < 1) repeatCount = 1; return true; }
bool BlockGenerator::GenerateTrack(WaveTrack *tmp, const WaveTrack &track, int ntrack) { bool bGoodResult = true; numSamples = track.TimeToLongSamples(GetDuration()); sampleCount i = 0; float *data = new float[tmp->GetMaxBlockSize()]; sampleCount block = 0; while ((i < numSamples) && bGoodResult) { block = tmp->GetBestBlockSize(i); if (block > (numSamples - i)) block = numSamples - i; GenerateBlock(data, track, block); // Add the generated data to the temporary track tmp->Append((samplePtr)data, floatSample, block); i += block; // Update the progress meter if (TrackProgress(ntrack, (double)i / numSamples)) bGoodResult = false; } delete[] data; return bGoodResult; }
bool EffectRepeat::Process() { this->CopyInputWaveTracks(); // Set up mOutputWaveTracks. bool bGoodResult = true; TrackListIterator iter(mOutputWaveTracks); WaveTrack *track = (WaveTrack *) iter.First(); int nTrack = 0; double maxDestLen = 0.0; // used to change selection to generated bit while ((track != NULL) && bGoodResult) { double trackStart = track->GetStartTime(); double trackEnd = track->GetEndTime(); double t0 = mT0 < trackStart? trackStart: mT0; double t1 = mT1 > trackEnd? trackEnd: mT1; if (t1 <= t0) continue; sampleCount start = track->TimeToLongSamples(t0); sampleCount end = track->TimeToLongSamples(t1); sampleCount len = (sampleCount)(end - start); double tLen = track->LongSamplesToTime(len); double tc = t0 + tLen; if (len <= 0) continue; Track *dest; track->Copy(t0, t1, &dest); for(int j=0; j<repeatCount; j++) { if (!track->Paste(tc, dest) || TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel. { bGoodResult = false; break; } tc += tLen; } if (tc > maxDestLen) maxDestLen = tc; delete dest; track = (WaveTrack *) iter.Next(); nTrack++; } if (bGoodResult) { // Change selection to just the generated bits. mT0 = mT1; mT1 = maxDestLen; } this->ReplaceProcessedWaveTracks(bGoodResult); return bGoodResult; }
void AudioPrefetch::prefetch(bool doSeek) { if (writePos == ~0U) { printf("AudioPrefetch::prefetch: invalid write position\n"); return; } if (song->loop() && !audio->bounce() && !extSyncFlag.value()) { const Pos& loop = song->rPos(); unsigned n = loop.frame() - writePos; if (n < segmentSize) { unsigned lpos = song->lPos().frame(); // adjust loop start so we get exact loop len if (n > lpos) n = 0; // printf("prefetch seek %d\n", writePos); writePos = lpos - n; } } WaveTrackList* tl = song->waves(); for (iWaveTrack it = tl->begin(); it != tl->end(); ++it) { WaveTrack* track = *it; // p3.3.29 // Save time. Don't bother if track is off. Track On/Off not designed for rapid repeated response (but mute is). if (track->off()) continue; int ch = track->channels(); float* bp[ch]; // printf("prefetch %d\n", writePos); if (track->prefetchFifo()->getWriteBuffer(ch, segmentSize, bp, writePos)) { // printf("AudioPrefetch::prefetch No write buffer!\n"); // p3.3.46 Was getting this... continue; } //track->fetchData(writePos, segmentSize, bp); track->fetchData(writePos, segmentSize, bp, doSeek); // p3.3.41 //fprintf(stderr, "AudioPrefetch::prefetch data: segmentSize:%ld %e %e %e %e\n", segmentSize, bp[0][0], bp[0][1], bp[0][2], bp[0][3]); } writePos += segmentSize; }