double BatchCommands::GetEndTime() { AudacityProject *project = GetActiveProject(); if( project == NULL ) { //wxMessageBox( wxT("No project to process!") ); return -1.0; } TrackList * tracks = project->GetTracks(); if( tracks == NULL ) { //wxMessageBox( wxT("No tracks to process!") ); return -1.0; } double endTime = tracks->GetEndTime(); return endTime; }
void TranscriptionToolBar::OnSelectSound(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_SelectSound]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); TrackListOfKindIterator iter(Track::Wave, tl); Track *t = iter.First(); //Make a track if(t) { auto wt = static_cast<const WaveTrack*>(t); sampleCount start, len; GetSamples(wt, &start, &len); //Adjust length to end if selection is null //if(len == 0) //len = wt->GetSequence()->GetNumSamples()-start; double rate = wt->GetRate(); auto newstart = mVk->OffBackward(*wt, start, start); auto newend = mVk->OffForward(*wt, start + len, (int)(tl->GetEndTime() * rate)); //reset the selection bounds. p->SetSel0(newstart.as_double() / rate); p->SetSel1(newend.as_double() / rate); p->RedrawProject(); } SetButton(false,mButtons[TTB_SelectSound]); }
void TranscriptionToolBar::OnSelectSound(wxCommandEvent & WXUNUSED(event)) { //If IO is busy, abort immediately if (gAudioIO->IsBusy()){ SetButton(false,mButtons[TTB_SelectSound]); return; } mVk->AdjustThreshold(GetSensitivity()); AudacityProject *p = GetActiveProject(); TrackList *tl = p->GetTracks(); if(auto wt = *tl->Any<const WaveTrack>().begin()) { sampleCount start, len; GetSamples(wt, &start, &len); //Adjust length to end if selection is null //if(len == 0) //len = wt->GetSequence()->GetNumSamples()-start; double rate = wt->GetRate(); auto newstart = mVk->OffBackward(*wt, start, start); auto newend = mVk->OffForward(*wt, start + len, (int)(tl->GetEndTime() * rate)); //reset the selection bounds. auto &selectedRegion = p->GetViewInfo().selectedRegion; selectedRegion.setTimes( newstart.as_double() / rate, newend.as_double() / rate ); p->RedrawProject(); } SetButton(false,mButtons[TTB_SelectSound]); }
void ControlToolBar::PlayPlayRegion(double t0, double t1, bool looped /* = false */, bool cutpreview /* = false */, TimeTrack *timetrack /* = NULL */, const double *pStartTime /* = NULL */) { SetPlay(true, looped, cutpreview); if (gAudioIO->IsBusy()) { SetPlay(false); return; } if (cutpreview && t0==t1) { SetPlay(false); return; /* msmeyer: makes no sense */ } AudacityProject *p = GetActiveProject(); if (!p) { SetPlay(false); return; // Should never happen, but... } TrackList *t = p->GetTracks(); if (!t) { mPlay->PopUp(); return; // Should never happen, but... } bool hasaudio = false; TrackListIterator iter(t); for (Track *trk = iter.First(); trk; trk = iter.Next()) { if (trk->GetKind() == Track::Wave #ifdef EXPERIMENTAL_MIDI_OUT || trk->GetKind() == Track::Note #endif ) { hasaudio = true; break; } } if (!hasaudio) { SetPlay(false); return; // No need to continue without audio tracks } double maxofmins,minofmaxs; #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR) double init_seek = 0.0; #endif // JS: clarified how the final play region is computed; if (t1 == t0) { // msmeyer: When playing looped, we play the whole file, if // no range is selected. Otherwise, we play from t0 to end if (looped) { // msmeyer: always play from start t0 = t->GetStartTime(); } else { // move t0 to valid range if (t0 < 0) { t0 = t->GetStartTime(); } else if (t0 > t->GetEndTime()) { t0 = t->GetEndTime(); } #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR) else { init_seek = t0; //AC: init_seek is where playback will 'start' t0 = t->GetStartTime(); } #endif } // always play to end t1 = t->GetEndTime(); } else { // always t0 < t1 right? // the set intersection between the play region and the // valid range maximum of lower bounds if (t0 < t->GetStartTime()) maxofmins = t->GetStartTime(); else maxofmins = t0; // minimum of upper bounds if (t1 > t->GetEndTime()) minofmaxs = t->GetEndTime(); else minofmaxs = t1; // we test if the intersection has no volume if (minofmaxs <= maxofmins) { // no volume; play nothing return; } else { t0 = maxofmins; t1 = minofmaxs; } } // Can't play before 0...either shifted or latencey corrected tracks if (t0 < 0.0) { t0 = 0.0; } bool success = false; if (t1 > t0) { int token; if (cutpreview) { double beforeLen, afterLen; gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0); gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0); double tcp0 = t0-beforeLen; double tcp1 = (t1+afterLen) - (t1-t0); SetupCutPreviewTracks(tcp0, t0, t1, tcp1); if (mCutPreviewTracks) { token = gAudioIO->StartStream( mCutPreviewTracks->GetWaveTrackArray(false), WaveTrackArray(), #ifdef EXPERIMENTAL_MIDI_OUT NoteTrackArray(), #endif timetrack, p->GetRate(), tcp0, tcp1, p, false, t0, t1-t0, pStartTime); } else { // Cannot create cut preview tracks, clean up and exit SetPlay(false); SetStop(false); SetRecord(false); return; } } else { if (!timetrack) { timetrack = t->GetTimeTrack(); } token = gAudioIO->StartStream(t->GetWaveTrackArray(false), WaveTrackArray(), #ifdef EXPERIMENTAL_MIDI_OUT t->GetNoteTrackArray(false), #endif timetrack, p->GetRate(), t0, t1, p, looped, 0, 0, pStartTime); } if (token != 0) { success = true; p->SetAudioIOToken(token); mBusyProject = p; #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR) //AC: If init_seek was set, now's the time to make it happen. gAudioIO->SeekStream(init_seek); #endif } else { // msmeyer: Show error message if stream could not be opened wxMessageBox( #if wxCHECK_VERSION(3,0,0) _("Error while opening sound device. " "Please check the playback device settings and the project sample rate."), #else _("Error while opening sound device. " wxT("Please check the playback device settings and the project sample rate.")), #endif _("Error"), wxOK | wxICON_EXCLAMATION, this); } } if (!success) { SetPlay(false); SetStop(false); SetRecord(false); } }
int ControlToolBar::PlayPlayRegion(const SelectedRegion &selectedRegion, const AudioIOStartStreamOptions &options, PlayMode mode, PlayAppearance appearance, /* = PlayOption::Straight */ bool backwards, /* = false */ bool playWhiteSpace /* = false */) { if (!CanStopAudioStream()) return -1; // Uncomment this for laughs! // backwards = true; double t0 = selectedRegion.t0(); double t1 = selectedRegion.t1(); // SelectedRegion guarantees t0 <= t1, so we need another boolean argument // to indicate backwards play. const bool looped = options.playLooped; if (backwards) std::swap(t0, t1); SetPlay(true, appearance); if (gAudioIO->IsBusy()) { SetPlay(false); return -1; } const bool cutpreview = appearance == PlayAppearance::CutPreview; if (cutpreview && t0==t1) { SetPlay(false); return -1; /* msmeyer: makes no sense */ } AudacityProject *p = GetActiveProject(); if (!p) { SetPlay(false); return -1; // Should never happen, but... } TrackList *t = p->GetTracks(); if (!t) { mPlay->PopUp(); return -1; // Should never happen, but... } p->mLastPlayMode = mode; bool hasaudio = false; TrackListIterator iter(t); for (Track *trk = iter.First(); trk; trk = iter.Next()) { if (trk->GetKind() == Track::Wave #ifdef EXPERIMENTAL_MIDI_OUT || trk->GetKind() == Track::Note #endif ) { hasaudio = true; break; } } double latestEnd = (playWhiteSpace)? t1 : t->GetEndTime(); if (!hasaudio) { SetPlay(false); return -1; // No need to continue without audio tracks } #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR) double init_seek = 0.0; #endif if (t1 == t0) { if (looped) { // play selection if there is one, otherwise // set start of play region to project start, // and loop the project from current play position. if ((t0 > p->GetSel0()) && (t0 < p->GetSel1())) { t0 = p->GetSel0(); t1 = p->GetSel1(); } else { // loop the entire project t0 = t->GetStartTime(); t1 = t->GetEndTime(); } } else { // move t0 to valid range if (t0 < 0) { t0 = t->GetStartTime(); } else if (t0 > t->GetEndTime()) { t0 = t->GetEndTime(); } #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR) else { init_seek = t0; //AC: init_seek is where playback will 'start' t0 = t->GetStartTime(); } #endif } t1 = t->GetEndTime(); } else { // maybe t1 < t0, with backwards scrubbing for instance if (backwards) std::swap(t0, t1); t0 = std::max(0.0, std::min(t0, latestEnd)); t1 = std::max(0.0, std::min(t1, latestEnd)); if (backwards) std::swap(t0, t1); } int token = -1; bool success = false; if (t1 != t0) { if (cutpreview) { const double tless = std::min(t0, t1); const double tgreater = std::max(t0, t1); double beforeLen, afterLen; gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0); gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0); double tcp0 = tless-beforeLen; double diff = tgreater - tless; double tcp1 = (tgreater+afterLen) - diff; SetupCutPreviewTracks(tcp0, tless, tgreater, tcp1); if (backwards) std::swap(tcp0, tcp1); if (mCutPreviewTracks) { AudioIOStartStreamOptions myOptions = options; myOptions.cutPreviewGapStart = t0; myOptions.cutPreviewGapLen = t1 - t0; token = gAudioIO->StartStream( mCutPreviewTracks->GetWaveTrackArray(false), WaveTrackArray(), #ifdef EXPERIMENTAL_MIDI_OUT NoteTrackArray(), #endif tcp0, tcp1, myOptions); } else { // Cannot create cut preview tracks, clean up and exit SetPlay(false); SetStop(false); SetRecord(false); return -1; } } else { // Lifted the following into AudacityProject::GetDefaultPlayOptions() /* if (!timetrack) { timetrack = t->GetTimeTrack(); } */ token = gAudioIO->StartStream(t->GetWaveTrackArray(false), WaveTrackArray(), #ifdef EXPERIMENTAL_MIDI_OUT t->GetNoteTrackArray(false), #endif t0, t1, options); } if (token != 0) { success = true; p->SetAudioIOToken(token); mBusyProject = p; #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR) //AC: If init_seek was set, now's the time to make it happen. gAudioIO->SeekStream(init_seek); #endif } else { // msmeyer: Show error message if stream could not be opened wxMessageBox( _("Error while opening sound device. " "Please check the playback device settings and the project sample rate."), _("Error"), wxOK | wxICON_EXCLAMATION, this); } } if (!success) { SetPlay(false); SetStop(false); SetRecord(false); return -1; } // Let other UI update appearance if (p) p->GetRulerPanel()->HideQuickPlayIndicator(); return token; }
bool AudacityPrintout::OnPrintPage(int page) { wxDC *dc = GetDC(); if (!dc) return false; int width, height; dc->GetSize(&width, &height); int rulerScreenHeight = 40; int screenTotalHeight = mTracks->GetHeight() + rulerScreenHeight; double scale = height / (double)screenTotalHeight; int rulerPageHeight = (int)(rulerScreenHeight * scale); Ruler ruler; ruler.SetBounds(0, 0, width, rulerPageHeight); ruler.SetOrientation(wxHORIZONTAL); ruler.SetRange(0.0, mTracks->GetEndTime()); ruler.SetFormat(Ruler::TimeFormat); ruler.SetLabelEdges(true); ruler.Draw(*dc); TrackArtist artist; artist.SetBackgroundBrushes(*wxWHITE_BRUSH, *wxWHITE_BRUSH, *wxWHITE_PEN, *wxWHITE_PEN); ViewInfo viewInfo; viewInfo.sel0 = viewInfo.sel1 = 0; viewInfo.vpos = 0; viewInfo.h = 0.0; viewInfo.screen = mTracks->GetEndTime() - viewInfo.h; viewInfo.total = viewInfo.screen; viewInfo.zoom = viewInfo.lastZoom = width / viewInfo.screen; int y = rulerPageHeight; TrackListIterator iter(mTracks); Track *n = iter.First(); while (n) { wxRect r; r.x = 0; r.y = y; r.width = width; r.height = (int)(n->GetHeight() * scale); switch(n->GetKind()) { case Track::Wave: switch (((WaveTrack *)n)->GetDisplay()) { case WaveTrack::WaveformDisplay: artist.DrawWaveform((WaveTrack *)n, *dc, r, &viewInfo, false, false, false, false, false); break; case WaveTrack::WaveformDBDisplay: artist.DrawWaveform((WaveTrack *)n, *dc, r, &viewInfo, false, false, false, true, false); break; case WaveTrack::SpectrumDisplay: artist.DrawSpectrum((WaveTrack *)n, *dc, r, &viewInfo, false); break; case WaveTrack::PitchDisplay: artist.DrawSpectrum((WaveTrack *)n, *dc, r, &viewInfo, true); break; } break; case Track::Note: artist.DrawNoteTrack((NoteTrack *)n, *dc, r, &viewInfo); break; case Track::Label: artist.DrawLabelTrack((LabelTrack *)n, *dc, r, &viewInfo); break; case Track::Time: artist.DrawTimeTrack((TimeTrack *)n, *dc, r, &viewInfo); break; } dc->SetPen(*wxBLACK_PEN); dc->DrawLine(0, r.y, width, r.y); n = iter.Next(); y += r.height; }; return true; }
bool AudacityPrintout::OnPrintPage(int WXUNUSED(page)) { wxDC *dc = GetDC(); if (!dc) return false; int width, height; dc->GetSize(&width, &height); int rulerScreenHeight = 40; int screenTotalHeight = mTracks->GetHeight() + rulerScreenHeight; double scale = height / (double)screenTotalHeight; int rulerPageHeight = (int)(rulerScreenHeight * scale); Ruler ruler; ruler.SetBounds(0, 0, width, rulerPageHeight); ruler.SetOrientation(wxHORIZONTAL); ruler.SetRange(0.0, mTracks->GetEndTime()); ruler.SetFormat(Ruler::TimeFormat); ruler.SetLabelEdges(true); ruler.Draw(*dc); TrackArtist artist; artist.SetBackgroundBrushes(*wxWHITE_BRUSH, *wxWHITE_BRUSH, *wxWHITE_PEN, *wxWHITE_PEN); const double screenDuration = mTracks->GetEndTime(); ZoomInfo zoomInfo(0.0, width / screenDuration); int y = rulerPageHeight; TrackListIterator iter(mTracks); Track *n = iter.First(); while (n) { wxRect r; r.x = 0; r.y = y; r.width = width; r.height = (int)(n->GetHeight() * scale); artist.DrawTrack(n, *dc, r, SelectedRegion(), zoomInfo, false, false, false, false); dc->SetPen(*wxBLACK_PEN); AColor::Line(*dc, 0, r.y, width, r.y); #ifdef EXPERIMENTAL_OUTPUT_DISPLAY if(MONO_WAVE_PAN(n)){ y += r.height; r.x = 0; r.y = y; r.width = width; r.height = (int)(n->GetHeight(true) * scale); artist.DrawTrack( n, *dc, r, SelectedRegion{}, zoomInfo, false, false, false, false); dc->SetPen(*wxBLACK_PEN); AColor::Line(*dc, 0, r.y, width, r.y); } #endif n = iter.Next(); y += r.height; }; return true; }
void ControlToolBar::PlayPlayRegion(double t0, double t1, bool looped /* = false */) { if (gAudioIO->IsBusy()) { mPlay->PopUp(); #if (AUDACITY_BRANDING == BRAND_THINKLABS) mLoopPlay->PopUp(); #elif (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) mPlay->Show(); mPause->Hide(); this->EnablePauseCommand(false); #endif return; } mStop->Enable(); mRewind->Disable(); mRecord->Disable(); mFF->Disable(); mPause->Enable(); this->EnablePauseCommand(true); AudacityProject *p = GetActiveProject(); if (p) { TrackList *t = p->GetTracks(); double maxofmins,minofmaxs; // JS: clarified how the final play region is computed; if (t1 == t0) { // msmeyer: When playing looped, we play the whole file, if // no range is selected. Otherwise, we play from t0 to end if (looped) { // msmeyer: always play from start t0 = t->GetStartTime(); } else { // move t0 to valid range if (t0 < 0) t0 = t->GetStartTime(); if (t0 > t->GetEndTime()) t0 = t->GetEndTime(); } // always play to end t1 = t->GetEndTime(); } else { // always t0 < t1 right? // the set intersection between the play region and the // valid range maximum of lower bounds if (t0 < t->GetStartTime()) maxofmins = t->GetStartTime(); else maxofmins = t0; // minimum of upper bounds if (t1 > t->GetEndTime()) minofmaxs = t->GetEndTime(); else minofmaxs = t1; // we test if the intersection has no volume if (minofmaxs <= maxofmins) { // no volume; play nothing return; } else { t0 = maxofmins; t1 = minofmaxs; } } bool success = false; if (t1 > t0) { int token = gAudioIO->StartStream(t->GetWaveTrackArray(false), WaveTrackArray(), t->GetTimeTrack(), p->GetRate(), t0, t1, looped); if (token != 0) { success = true; p->SetAudioIOToken(token); mBusyProject = p; SetVUMeters(p); } else { // msmeyer: Show error message if stream could not be opened wxMessageBox(_("Error while opening sound device. Please check the output " "device settings and the project sample rate."), _("Error"), wxOK | wxICON_EXCLAMATION, this); } } if (!success) { SetPlay(false); SetStop(false); SetRecord(false); } #if (AUDACITY_BRANDING == BRAND_AUDIOTOUCH) if (success) { mPlay->Hide(); mPause->Show(); this->EnablePauseCommand(true); this->SetBackgroundColour(*wxGREEN); // green for Playing this->Refresh(); } #endif } }
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 } }