void AudacityProject::OnNewWaveTrack(wxEvent & event) { WaveTrack *t = new WaveTrack(&mDirManager); t->SetSampleFormat(mDefaultFormat); t->SetRate(mRate); SelectNone(); mTracks->Add(t); t->SetSelected(true); PushState(_("Created new audio track")); FixScrollbars(); mTrackPanel->Refresh(false); }
bool EffectToneGen::Process() { if (length <= 0.0) length = sDefaultGenerateLen; //Iterate over each track TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *)iter.First(); while (track) { mSample = 0; WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat()); mCurRate = track->GetRate(); tmp->SetRate(mCurRate); longSampleCount numSamples = (longSampleCount)(length * mCurRate + 0.5); longSampleCount i = 0; float *data = new float[tmp->GetMaxBlockSize()]; sampleCount block; while(i < numSamples) { block = tmp->GetBestBlockSize(i); if (block > (numSamples - i)) block = numSamples - i; MakeTone(data, block); tmp->Append((samplePtr)data, floatSample, block); i += block; } delete[] data; tmp->Flush(); track->Clear(mT0, mT1); track->Paste(mT0, tmp); delete tmp; //Iterate to the next track track = (WaveTrack *)iter.Next(); } mT1 = mT0 + length; // Update selection. return true; }
bool QuickMix(TrackList *tracks, DirManager *dirManager, double rate, sampleFormat format) { WaveTrack **waveArray; VTrack *t; int numWaves = 0; int numLeft = 0; int numRight = 0; int numMono = 0; bool mono = false; int w; TrackListIterator iter(tracks); t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == VTrack::Wave) { numWaves++; switch (t->GetChannel()) { case VTrack::MonoChannel: numLeft++; numRight++; numMono++; break; case VTrack::LeftChannel: numLeft++; break; case VTrack::RightChannel: numRight++; break; } } t = iter.Next(); } if (numMono == numWaves || numLeft == numWaves || numRight == numWaves) mono = true; double totalTime = 0.0; waveArray = new WaveTrack *[numWaves]; w = 0; t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == VTrack::Wave) { waveArray[w++] = (WaveTrack *) t; if (t->GetMaxLen() > totalTime) totalTime = t->GetMaxLen(); } t = iter.Next(); } WaveTrack *mixLeft = new WaveTrack(dirManager); mixLeft->SetSampleFormat(format); mixLeft->SetRate(rate); mixLeft->SetChannel(VTrack::MonoChannel); mixLeft->SetName(_("Mix")); WaveTrack *mixRight = 0; if (!mono) { mixRight = new WaveTrack(dirManager); mixRight->SetSampleFormat(format); mixRight->SetRate(rate); mixRight->SetName(_("Mix")); mixLeft->SetChannel(VTrack::LeftChannel); mixRight->SetChannel(VTrack::RightChannel); mixLeft->SetLinked(true); } int maxBlockLen = mixLeft->GetIdealBlockSize(); double maxBlockTime = maxBlockLen / mixLeft->GetRate(); Mixer *mixer = new Mixer(mono ? 1 : 2, maxBlockLen, false, rate, format); wxProgressDialog *progress = NULL; wxYield(); wxStartTimer(); wxBusyCursor busy; double tt = 0.0; while (tt < totalTime) { double blockTime = maxBlockTime; if (tt + blockTime > totalTime) blockTime = totalTime - tt; int blockLen = int (blockTime * mixLeft->GetRate()); mixer->Clear(); for (int i = 0; i < numWaves; i++) { if (mono) mixer->MixMono(waveArray[i], tt, tt + blockTime); else { switch (waveArray[i]->GetChannel()) { case VTrack::LeftChannel: mixer->MixLeft(waveArray[i], tt, tt + blockTime); break; case VTrack::RightChannel: mixer->MixRight(waveArray[i], tt, tt + blockTime); break; case VTrack::MonoChannel: mixer->MixMono(waveArray[i], tt, tt + blockTime); break; } } } if (mono) { samplePtr buffer = mixer->GetBuffer(); mixLeft->Append(buffer, format, blockLen); } else { samplePtr buffer; buffer = mixer->GetBuffer(0); mixLeft->Append(buffer, format, blockLen); buffer = mixer->GetBuffer(1); mixRight->Append(buffer, format, blockLen); } tt += blockTime; if (!progress && wxGetElapsedTime(false) > 500) { progress = new wxProgressDialog(_("Quick Mix"), _("Mixing tracks"), 1000); } if (progress) { int progressvalue = int (1000 * (tt / totalTime)); progress->Update(progressvalue); } } tracks->Add(mixLeft); if (!mono) tracks->Add(mixRight); delete progress; int elapsedMS = wxGetElapsedTime(); double elapsedTime = elapsedMS * 0.001; double maxTracks = totalTime / (elapsedTime / numWaves); #ifdef __WXGTK__ printf(_(" Tracks: %d\n"), numWaves); printf(_(" Mix length: %f sec\n"), totalTime); printf(_("Elapsed time: %f sec\n"), elapsedTime); printf(_("Max number of tracks to mix in real time: %f\n"), maxTracks); #endif delete waveArray; delete mixer; return true; }
bool MixAndRender(TrackList *tracks, TrackFactory *trackFactory, double rate, sampleFormat format, double startTime, double endTime, WaveTrack **newLeft, WaveTrack **newRight) { // This function was formerly known as "Quick Mix". It takes one or // more tracks as input; of all tracks that are selected, it mixes // them together, applying any envelopes, amplitude gain, panning, // and real-time effects in the process. The resulting pair of // tracks (stereo) are "rendered" and have no effects, gain, panning, // or envelopes. WaveTrack **waveArray; Track *t; int numWaves = 0; int numMono = 0; bool mono = false; int w; TrackListIterator iter(tracks); t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == Track::Wave) { numWaves++; float pan = ((WaveTrack*)t)->GetPan(); if (t->GetChannel() == Track::MonoChannel && pan == 0) numMono++; } t = iter.Next(); } if (numMono == numWaves) mono = true; double totalTime = 0.0; waveArray = new WaveTrack *[numWaves]; w = 0; t = iter.First(); while (t) { if (t->GetSelected() && t->GetKind() == Track::Wave) { waveArray[w++] = (WaveTrack *) t; if (t->GetEndTime() > totalTime) totalTime = t->GetEndTime(); } t = iter.Next(); } WaveTrack *mixLeft = trackFactory->NewWaveTrack(format); mixLeft->SetRate((int) rate); mixLeft->SetName(_("Mix")); WaveTrack *mixRight = 0; if (mono) { mixLeft->SetChannel(Track::MonoChannel); } else { mixRight = trackFactory->NewWaveTrack(format); mixRight->SetRate((int) rate); mixRight->SetName(_("Mix")); mixLeft->SetChannel(Track::LeftChannel); mixRight->SetChannel(Track::RightChannel); mixLeft->SetLinked(true); } int maxBlockLen = mixLeft->GetIdealBlockSize(); if (startTime == endTime) { startTime = 0.0; endTime = totalTime; } Mixer *mixer = new Mixer(numWaves, waveArray, tracks->GetTimeTrack(), startTime, endTime, mono ? 1 : 2, maxBlockLen, false, rate, format); wxProgressDialog *progress = NULL; wxYield(); wxStartTimer(); wxBusyCursor busy; bool cancelling = false; while(!cancelling) { sampleCount blockLen = mixer->Process(maxBlockLen); if (blockLen == 0) break; if (mono) { samplePtr buffer = mixer->GetBuffer(); mixLeft->Append(buffer, format, blockLen); } else { samplePtr buffer; buffer = mixer->GetBuffer(0); mixLeft->Append(buffer, format, blockLen); buffer = mixer->GetBuffer(1); mixRight->Append(buffer, format, blockLen); } if (!progress && wxGetElapsedTime(false) > 500) { progress = new wxProgressDialog(_("Mix and Render"), _("Mixing and rendering tracks"), 1000); } if (progress) { int progressvalue = int (1000 * (mixer->MixGetCurrentTime() / totalTime)); cancelling = !progress->Update(progressvalue); } } mixLeft->Flush(); *newLeft = mixLeft; if (!mono) { mixRight->Flush(); *newRight = mixRight; } delete progress; #if 0 int elapsedMS = wxGetElapsedTime(); double elapsedTime = elapsedMS * 0.001; double maxTracks = totalTime / (elapsedTime / numWaves); // Note: these shouldn't be translated - they're for debugging // and profiling only. printf(" Tracks: %d\n", numWaves); printf(" Mix length: %f sec\n", totalTime); printf("Elapsed time: %f sec\n", elapsedTime); printf("Max number of tracks to mix in real time: %f\n", maxTracks); #endif delete[] waveArray; delete mixer; return true; }
void ControlToolBar::OnRecord(wxCommandEvent &evt) { if (gAudioIO->IsBusy()) { #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) if (mIsLocked) // Stop only if in locked mode. { this->StopPlaying(); // Stop recording. mRecord->PopUp(); } else { //v evt.GetClassInfo(); } #else mRecord->PopUp(); #endif return; } mPlay->Disable(); #if (AUDACITY_BRANDING == BRAND_THINKLABS) mLoopPlay->Disable(); #endif #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) mStop->SetEnabled(mIsLocked); #else mStop->Enable(); #endif mRewind->Disable(); mFF->Disable(); #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) mPause->SetEnabled(mIsLocked); this->EnablePauseCommand(mIsLocked); this->SetRecord(mIsLocked); // If locked, push Record down, else up. #else mPause->Enable(); mRecord->PushDown(); #endif AudacityProject *p = GetActiveProject(); if (p) { TrackList *t = p->GetTracks(); // Don't do this for Audiotouch. Not necessary. The performance hit is in the track being recorded, below. #if (AUDACITY_BRANDING == BRAND_THINKLABS) // For versions that default to dual wave/spectrum display, // switch all tracks to WaveformDisplay on Record, for performance. TrackListIterator iter(t); for (Track* pTrack = iter.First(); pTrack; pTrack = iter.Next()) if (pTrack->GetKind() == Track::Wave) ((WaveTrack*)pTrack)->SetDisplay(WaveTrack::WaveformDisplay); #endif double t0 = p->GetSel0(); double t1 = p->GetSel1(); if (t1 == t0) t1 = 1000000000.0; // record for a long, long time (tens of years) #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) if (p->m_bWantAppendRecording) { t0 = t->GetEndTime(); t1 = 1000000000.0; // record for a long, long time (tens of years) } gAudioIO->SetWantLatencyCorrection(!p->m_bWantAppendRecording); #endif /* TODO: set up stereo tracks if that is how the user has set up * their preferences, and choose sample format based on prefs */ WaveTrackArray newRecordingTracks, playbackTracks; bool duplex; gPrefs->Read("/AudioIO/Duplex", &duplex, true); int recordingChannels = gPrefs->Read("/AudioIO/RecordChannels", 1); if( duplex ) playbackTracks = t->GetWaveTrackArray(false); else playbackTracks = WaveTrackArray(); for( int c = 0; c < recordingChannels; c++ ) { WaveTrack *newTrack = p->GetTrackFactory()->NewWaveTrack(); newTrack->SetOffset(t0); newTrack->SetRate(p->GetRate()); //v for performance newTrack->SetDisplay(WaveTrack::WaveformAndSpectrumDisplay); newTrack->SetDisplay(WaveTrack::WaveformDisplay); if( recordingChannels == 2 ) { if( c == 0 ) { newTrack->SetChannel(Track::LeftChannel); newTrack->SetLinked(true); } else newTrack->SetChannel(Track::RightChannel); } else { newTrack->SetChannel( Track::MonoChannel ); } newRecordingTracks.Add(newTrack); } int token = gAudioIO->StartStream(playbackTracks, newRecordingTracks, t->GetTimeTrack(), p->GetRate(), t0, t1); bool success = (token != 0); for( unsigned int i = 0; i < newRecordingTracks.GetCount(); i++ ) if (success) t->Add(newRecordingTracks[i]); else delete newRecordingTracks[i]; if (success) { p->SetAudioIOToken(token); mBusyProject = p; SetVUMeters(p); #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) this->SetBackgroundColour(*wxRED); // red for Recording this->Refresh(); #endif } else { // msmeyer: Show error message if stream could not be opened wxMessageBox(_("Error while opening sound device. Please check the input " "device settings and the project sample rate."), _("Error"), wxOK | wxICON_EXCLAMATION, this); SetPlay(false); #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) mStop->Enable(); // In case it was disabled above, based on mIsLocked. #endif SetStop(false); SetRecord(false); } #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) p->OnZoomFitV(); #endif } }