// Come here from button clicks, or commands void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) { // Can't do anything without an active project AudacityProject * p = GetActiveProject(); if (!p) { return; } // Create a TimeTrack if we haven't done so already if (!mTimeTrack) { mTimeTrack = p->GetTrackFactory()->NewTimeTrack(); if (!mTimeTrack) { return; } } // Pop up the button SetButton(false, mButtons[TTB_PlaySpeed]); // If IO is busy, abort immediately if (gAudioIO->IsBusy()) { p->GetControlToolBar()->StopPlaying(); } // Set the speed range //mTimeTrack->SetRangeUpper((double)mPlaySpeed / 100.0); //mTimeTrack->SetRangeLower((double)mPlaySpeed / 100.0); mTimeTrack->GetEnvelope()->Flatten((double)mPlaySpeed / 100.0); // Get the current play region double playRegionStart, playRegionEnd; p->GetPlayRegion(&playRegionStart, &playRegionEnd); // Start playing if (playRegionStart >= 0) { // playRegionEnd = playRegionStart + (playRegionEnd-playRegionStart)* 100.0/mPlaySpeed; #ifdef EXPERIMENTAL_MIDI_OUT gAudioIO->SetMidiPlaySpeed(mPlaySpeed); #endif AudioIOStartStreamOptions options(p->GetDefaultPlayOptions()); options.playLooped = looped; options.timeTrack = mTimeTrack.get(); ControlToolBar::PlayAppearance appearance = cutPreview ? ControlToolBar::PlayAppearance::CutPreview : looped ? ControlToolBar::PlayAppearance::Looped : ControlToolBar::PlayAppearance::Straight; p->GetControlToolBar()->PlayPlayRegion (SelectedRegion(playRegionStart, playRegionEnd), options, PlayMode::normalPlay, appearance); } }
void ControlToolBar::OnRecord(wxCommandEvent &evt) { if (gAudioIO->IsBusy()) { mRecord->PopUp(); return; } AudacityProject *p = GetActiveProject(); if( evt.GetInt() == 1 ) // used when called by keyboard shortcut. Default (0) ignored. mRecord->SetShift(true); if( evt.GetInt() == 2 ) mRecord->SetShift(false); SetRecord(true, mRecord->WasShiftDown()); if (p) { TrackList *t = p->GetTracks(); TrackListIterator it(t); if(it.First() == NULL) mRecord->SetShift(false); double t0 = p->GetSel0(); double t1 = p->GetSel1(); if (t1 == t0) t1 = 1000000000.0; // record for a long, long time (tens of years) /* 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; #ifdef EXPERIMENTAL_MIDI_OUT NoteTrackArray midiTracks; #endif bool duplex; gPrefs->Read(wxT("/AudioIO/Duplex"), &duplex, true); if(duplex){ playbackTracks = t->GetWaveTrackArray(false); #ifdef EXPERIMENTAL_MIDI_OUT midiTracks = t->GetNoteTrackArray(false); #endif } else { playbackTracks = WaveTrackArray(); #ifdef EXPERIMENTAL_MIDI_OUT midiTracks = NoteTrackArray(); #endif } // If SHIFT key was down, the user wants append to tracks int recordingChannels = 0; bool shifted = mRecord->WasShiftDown(); if (shifted) { bool sel = false; double allt0 = t0; // Find the maximum end time of selected and all wave tracks // Find whether any tracks were selected. (If any are selected, // record only into them; else if tracks exist, record into all.) for (Track *tt = it.First(); tt; tt = it.Next()) { if (tt->GetKind() == Track::Wave) { WaveTrack *wt = static_cast<WaveTrack *>(tt); if (wt->GetEndTime() > allt0) { allt0 = wt->GetEndTime(); } if (tt->GetSelected()) { sel = true; if (wt->GetEndTime() > t0) { t0 = wt->GetEndTime(); } } } } // Use end time of all wave tracks if none selected if (!sel) { t0 = allt0; } // Pad selected/all wave tracks to make them all the same length // Remove recording tracks from the list of tracks for duplex ("overdub") // playback. for (Track *tt = it.First(); tt; tt = it.Next()) { if (tt->GetKind() == Track::Wave && (tt->GetSelected() || !sel)) { WaveTrack *wt = static_cast<WaveTrack *>(tt); if (duplex) playbackTracks.Remove(wt); t1 = wt->GetEndTime(); if (t1 < t0) { WaveTrack *newTrack = p->GetTrackFactory()->NewWaveTrack(); newTrack->InsertSilence(0.0, t0 - t1); newTrack->Flush(); wt->Clear(t1, t0); bool bResult = wt->Paste(t1, newTrack); wxASSERT(bResult); // TO DO: Actually handle this. delete newTrack; } newRecordingTracks.Add(wt); } } t1 = 1000000000.0; // record for a long, long time (tens of years) } else { recordingChannels = gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2); for (int c = 0; c < recordingChannels; c++) { WaveTrack *newTrack = p->GetTrackFactory()->NewWaveTrack(); newTrack->SetOffset(t0); if (recordingChannels > 2) newTrack->SetMinimized(true); 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); } // msmeyer: StartStream calls a callback which triggers auto-save, so // we add the tracks where recording is done into now. We remove them // later if starting the stream fails for (unsigned int i = 0; i < newRecordingTracks.GetCount(); i++) t->Add(newRecordingTracks[i]); } //Automated Input Level Adjustment Initialization #ifdef AUTOMATED_INPUT_LEVEL_ADJUSTMENT gAudioIO->AILAInitialize(); #endif int token = gAudioIO->StartStream(playbackTracks, newRecordingTracks, #ifdef EXPERIMENTAL_MIDI_OUT midiTracks, #endif t->GetTimeTrack(), p->GetRate(), t0, t1, p); bool success = (token != 0); if (success) { p->SetAudioIOToken(token); mBusyProject = p; } else { // msmeyer: Delete recently added tracks if opening stream fails if (!shifted) { for (unsigned int i = 0; i < newRecordingTracks.GetCount(); i++) { t->Remove(newRecordingTracks[i]); delete newRecordingTracks[i]; } } // msmeyer: Show error message if stream could not be opened wxMessageBox(_("Error while opening sound device. Please check the recording device settings and the project sample rate."), _("Error"), wxOK | wxICON_EXCLAMATION, this); SetPlay(false); SetStop(false); SetRecord(false); } } }
void ControlToolBar::OnRecord(wxCommandEvent &evt) { auto doubleClicked = mRecord->IsDoubleClicked(); mRecord->ClearDoubleClicked(); if (doubleClicked) { // Display a fixed recording head while scrolling the waves continuously. // If you overdub, you may want to anticipate some context in existing tracks, // so center the head. If not, put it rightmost to display as much wave as we can. const auto project = GetActiveProject(); bool duplex; gPrefs->Read(wxT("/AudioIO/Duplex"), &duplex, true); if (duplex) { // See if there is really anything being overdubbed if (gAudioIO->GetNumPlaybackChannels() == 0) // No. duplex = false; } using Mode = AudacityProject::PlaybackScroller::Mode; project->GetPlaybackScroller().Activate(duplex ? Mode::Centered : Mode::Right); return; } if (gAudioIO->IsBusy()) { if (!CanStopAudioStream() || 0 == gAudioIO->GetNumCaptureChannels()) mRecord->PopUp(); else mRecord->PushDown(); return; } AudacityProject *p = GetActiveProject(); if( evt.GetInt() == 1 ) // used when called by keyboard shortcut. Default (0) ignored. mRecord->SetShift(true); if( evt.GetInt() == 2 ) mRecord->SetShift(false); SetRecord(true, mRecord->WasShiftDown()); if (p) { TrackList *trackList = p->GetTracks(); TrackListIterator it(trackList); if(it.First() == NULL) mRecord->SetShift(false); double t0 = p->GetSel0(); double t1 = p->GetSel1(); if (t1 == t0) t1 = 1000000000.0; // record for a long, long time (tens of years) /* 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; #ifdef EXPERIMENTAL_MIDI_OUT NoteTrackArray midiTracks; #endif bool duplex; gPrefs->Read(wxT("/AudioIO/Duplex"), &duplex, true); if(duplex){ playbackTracks = trackList->GetWaveTrackArray(false); #ifdef EXPERIMENTAL_MIDI_OUT midiTracks = trackList->GetNoteTrackArray(false); #endif } else { playbackTracks = WaveTrackArray(); #ifdef EXPERIMENTAL_MIDI_OUT midiTracks = NoteTrackArray(); #endif } // If SHIFT key was down, the user wants append to tracks int recordingChannels = 0; TrackList tracksCopy{}; bool tracksCopied = false; bool shifted = mRecord->WasShiftDown(); if (shifted) { bool sel = false; double allt0 = t0; // Find the maximum end time of selected and all wave tracks // Find whether any tracks were selected. (If any are selected, // record only into them; else if tracks exist, record into all.) for (Track *tt = it.First(); tt; tt = it.Next()) { if (tt->GetKind() == Track::Wave) { WaveTrack *wt = static_cast<WaveTrack *>(tt); if (wt->GetEndTime() > allt0) { allt0 = wt->GetEndTime(); } if (tt->GetSelected()) { sel = true; if (wt->GetEndTime() > t0) { t0 = wt->GetEndTime(); } } } } // Use end time of all wave tracks if none selected if (!sel) { t0 = allt0; } // Pad selected/all wave tracks to make them all the same length // Remove recording tracks from the list of tracks for duplex ("overdub") // playback. for (Track *tt = it.First(); tt; tt = it.Next()) { if (tt->GetKind() == Track::Wave && (tt->GetSelected() || !sel)) { WaveTrack *wt = static_cast<WaveTrack *>(tt); if (duplex) { auto end = playbackTracks.end(); auto it = std::find(playbackTracks.begin(), end, wt); if (it != end) playbackTracks.erase(it); } t1 = wt->GetEndTime(); if (t1 < t0) { if (!tracksCopied) { tracksCopied = true; tracksCopy = *trackList; } auto newTrack = p->GetTrackFactory()->NewWaveTrack(); newTrack->InsertSilence(0.0, t0 - t1); newTrack->Flush(); wt->Clear(t1, t0); bool bResult = wt->Paste(t1, newTrack.get()); wxASSERT(bResult); // TO DO: Actually handle this. wxUnusedVar(bResult); } newRecordingTracks.push_back(wt); } } t1 = 1000000000.0; // record for a long, long time (tens of years) } else { bool recordingNameCustom, useTrackNumber, useDateStamp, useTimeStamp; wxString defaultTrackName, defaultRecordingTrackName; int numTracks = 0; for (Track *tt = it.First(); tt; tt = it.Next()) { if (tt->GetKind() == Track::Wave && !tt->GetLinked()) numTracks++; } numTracks++; recordingChannels = gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2); gPrefs->Read(wxT("/GUI/TrackNames/RecordingNameCustom"), &recordingNameCustom, false); gPrefs->Read(wxT("/GUI/TrackNames/TrackNumber"), &useTrackNumber, false); gPrefs->Read(wxT("/GUI/TrackNames/DateStamp"), &useDateStamp, false); gPrefs->Read(wxT("/GUI/TrackNames/TimeStamp"), &useTimeStamp, false); /* i18n-hint: The default name for an audio track. */ gPrefs->Read(wxT("/GUI/TrackNames/DefaultTrackName"),&defaultTrackName, _("Audio Track")); gPrefs->Read(wxT("/GUI/TrackNames/RecodingTrackName"), &defaultRecordingTrackName, defaultTrackName); wxString baseTrackName = recordingNameCustom? defaultRecordingTrackName : defaultTrackName; for (int c = 0; c < recordingChannels; c++) { auto newTrack = p->GetTrackFactory()->NewWaveTrack(); newTrack->SetOffset(t0); wxString nameSuffix = wxString(wxT("")); if (useTrackNumber) { nameSuffix += wxString::Format(wxT("%d"), numTracks + c); } if (useDateStamp) { if (!nameSuffix.IsEmpty()) { nameSuffix += wxT("_"); } nameSuffix += wxDateTime::Now().FormatISODate(); } if (useTimeStamp) { if (!nameSuffix.IsEmpty()) { nameSuffix += wxT("_"); } nameSuffix += wxDateTime::Now().FormatISOTime(); } // ISO standard would be nice, but ":" is unsafe for file name. nameSuffix.Replace(wxT(":"), wxT("-")); if (baseTrackName.IsEmpty()) { newTrack->SetName(nameSuffix); } else if (nameSuffix.IsEmpty()) { newTrack->SetName(baseTrackName); } else { newTrack->SetName(baseTrackName + wxT("_") + nameSuffix); } if (recordingChannels > 2) newTrack->SetMinimized(true); if (recordingChannels == 2) { if (c == 0) { newTrack->SetChannel(Track::LeftChannel); newTrack->SetLinked(true); } else { newTrack->SetChannel(Track::RightChannel); } } else { newTrack->SetChannel( Track::MonoChannel ); } // Let the list hold the track, and keep a pointer to it newRecordingTracks.push_back( static_cast<WaveTrack*>( trackList->Add( std::move(newTrack)))); } } //Automated Input Level Adjustment Initialization #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT gAudioIO->AILAInitialize(); #endif AudioIOStartStreamOptions options(p->GetDefaultPlayOptions()); int token = gAudioIO->StartStream(playbackTracks, newRecordingTracks, #ifdef EXPERIMENTAL_MIDI_OUT midiTracks, #endif t0, t1, options); bool success = (token != 0); if (success) { p->SetAudioIOToken(token); mBusyProject = p; } else { if (shifted) { // Restore the tracks to remove any inserted silence if (tracksCopied) *trackList = std::move(tracksCopy); } else { // msmeyer: Delete recently added tracks if opening stream fails for (unsigned int i = 0; i < newRecordingTracks.size(); i++) { trackList->Remove(newRecordingTracks[i]); } } // msmeyer: Show error message if stream could not be opened wxMessageBox(_("Error while opening sound device. Please check the recording device settings and the project sample rate."), _("Error"), wxOK | wxICON_EXCLAMATION, this); SetPlay(false); SetStop(false); SetRecord(false); } } UpdateStatusBar(GetActiveProject()); }
bool EffectStereoToMono::Process() { // Do not use mWaveTracks here. We will possibly delete tracks, // so we must use the "real" tracklist. this->CopyInputTracks(); // Set up mOutputTracks. bool bGoodResult = true; SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks); mLeftTrack = (WaveTrack *)iter.First(); bool refreshIter = false; if(mLeftTrack) { // create a new WaveTrack to hold all of the output AudacityProject *p = GetActiveProject(); mOutTrack = p->GetTrackFactory()->NewWaveTrack(floatSample, mLeftTrack->GetRate()); } int count = 0; while (mLeftTrack) { if (mLeftTrack->GetKind() == Track::Wave && mLeftTrack->GetSelected() && mLeftTrack->GetLinked()) { mRightTrack = (WaveTrack *)iter.Next(); if ((mLeftTrack->GetRate() == mRightTrack->GetRate())) { sampleCount leftTrackStart = mLeftTrack->TimeToLongSamples(mLeftTrack->GetStartTime()); sampleCount rightTrackStart = mRightTrack->TimeToLongSamples(mRightTrack->GetStartTime()); mStart = wxMin(leftTrackStart, rightTrackStart); sampleCount leftTrackEnd = mLeftTrack->TimeToLongSamples(mLeftTrack->GetEndTime()); sampleCount rightTrackEnd = mRightTrack->TimeToLongSamples(mRightTrack->GetEndTime()); mEnd = wxMax(leftTrackEnd, rightTrackEnd); bGoodResult = ProcessOne(count); if (!bGoodResult) break; mOutTrack->Clear(mOutTrack->GetStartTime(), mOutTrack->GetEndTime()); // The right channel has been deleted, so we must restart from the beginning refreshIter = true; } } if (refreshIter) { mLeftTrack = (WaveTrack *)iter.First(); refreshIter = false; } else { mLeftTrack = (WaveTrack *)iter.Next(); } count++; } if(mOutTrack) delete mOutTrack; this->ReplaceProcessedTracks(bGoodResult); return bGoodResult; }
// Come here from button clicks, or commands void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) { // Can't do anything without an active project AudacityProject * p = GetActiveProject(); if (!p) { return; } // Fixed speed play is the old method, that uses a time track. // VariSpeed play reuses Scrubbing. bool bFixedSpeedPlay = !gPrefs->ReadBool(wxT("/AudioIO/VariSpeedPlay"), true); // Scrubbing doesn't support note tracks, but the fixed-speed method using time tracks does. if (p->GetTracks()->Any<NoteTrack>()) bFixedSpeedPlay = true; // Scrubbing only supports straight through play. // So if looped or cutPreview, we have to fall back to fixed speed. bFixedSpeedPlay = bFixedSpeedPlay || looped || cutPreview; if (bFixedSpeedPlay) { // Create a TimeTrack if we haven't done so already if (!mTimeTrack) { mTimeTrack = p->GetTrackFactory()->NewTimeTrack(); if (!mTimeTrack) { return; } } // Set the speed range //mTimeTrack->SetRangeUpper((double)mPlaySpeed / 100.0); //mTimeTrack->SetRangeLower((double)mPlaySpeed / 100.0); mTimeTrack->GetEnvelope()->Flatten((double)mPlaySpeed / 100.0); } // Pop up the button SetButton(false, mButtons[TTB_PlaySpeed]); // If IO is busy, abort immediately if (gAudioIO->IsBusy()) { p->GetControlToolBar()->StopPlaying(); } // Get the current play region double playRegionStart, playRegionEnd; p->GetPlayRegion(&playRegionStart, &playRegionEnd); // Start playing if (playRegionStart < 0) return; if (bFixedSpeedPlay) { AudioIOStartStreamOptions options(p->GetDefaultPlayOptions()); options.playLooped = looped; // No need to set cutPreview options. // Due to a rather hacky approach, the appearance is used // to signal use of cutpreview to code below. options.timeTrack = mTimeTrack.get(); ControlToolBar::PlayAppearance appearance = cutPreview ? ControlToolBar::PlayAppearance::CutPreview : looped ? ControlToolBar::PlayAppearance::Looped : ControlToolBar::PlayAppearance::Straight; p->GetControlToolBar()->PlayPlayRegion (SelectedRegion(playRegionStart, playRegionEnd), options, PlayMode::normalPlay, appearance); } else { Scrubber &Scrubber = p->GetScrubber(); Scrubber.StartSpeedPlay(GetPlaySpeed(), playRegionStart, playRegionEnd); } }
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 } }
void ControlToolBar::OnRecord(wxCommandEvent &evt) { if (gAudioIO->IsBusy()) { mRecord->PopUp(); return; } AudacityProject *p = GetActiveProject(); if (p && p->GetCleanSpeechMode()) { size_t numProjects = gAudacityProjects.Count(); bool tracks = (p && !p->GetTracks()->IsEmpty()); if (tracks || (numProjects > 1)) { wxMessageBox(_("Recording in CleanSpeech mode is not possible when a track, or more than one project, is already open."), _("Recording not permitted"), wxOK | wxICON_INFORMATION, this); mRecord->PopUp(); mRecord->Disable(); return; } } if( evt.GetInt() == 1 ) // used when called by keyboard shortcut. Default (0) ignored. mRecord->SetShift(true); if( evt.GetInt() == 2 ) mRecord->SetShift(false); SetRecord(true); if (p) { TrackList *t = p->GetTracks(); TrackListIterator it(t); if(it.First() == NULL) mRecord->SetShift(false); double t0 = p->GetSel0(); double t1 = p->GetSel1(); if (t1 == t0) t1 = 1000000000.0; // record for a long, long time (tens of years) /* 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; /* REQUIRES PORTMIDI */ // NoteTrackArray midiTracks; bool duplex; gPrefs->Read(wxT("/AudioIO/Duplex"), &duplex, true); if(duplex){ playbackTracks = t->GetWaveTrackArray(false); /* REQUIRES PORTMIDI */ // midiTracks = t->GetNoteTrackArray(false); } else { playbackTracks = WaveTrackArray(); /* REQUIRES PORTMIDI */ // midiTracks = NoteTrackArray(); } // If SHIFT key was down, the user wants append to tracks int recordingChannels = 0; bool shifted = mRecord->WasShiftDown(); if (shifted) { TrackListIterator it(t); WaveTrack *wt; bool sel = false; double allt0 = t0; // Find the maximum end time of selected and all wave tracks for (Track *tt = it.First(); tt; tt = it.Next()) { if (tt->GetKind() == Track::Wave) { wt = (WaveTrack *)tt; if (wt->GetEndTime() > allt0) { allt0 = wt->GetEndTime(); } if (tt->GetSelected()) { sel = true; if (duplex) playbackTracks.Remove(wt); if (wt->GetEndTime() > t0) { t0 = wt->GetEndTime(); } } } } // Use end time of all wave tracks if none selected if (!sel) { t0 = allt0; } // Pad selected/all wave tracks to make them all the same length for (Track *tt = it.First(); tt; tt = it.Next()) { if (tt->GetKind() == Track::Wave && (tt->GetSelected() || !sel)) { wt = (WaveTrack *)tt; t1 = wt->GetEndTime(); if (t1 < t0) { WaveTrack *newTrack = p->GetTrackFactory()->NewWaveTrack(); newTrack->InsertSilence(0.0, t0 - t1); newTrack->Flush(); wt->Clear(t1, t0); wt->Paste(t1, newTrack); delete newTrack; } newRecordingTracks.Add(wt); } } t1 = 1000000000.0; // record for a long, long time (tens of years) } else { recordingChannels = gPrefs->Read(wxT("/AudioIO/RecordChannels"), 2); for (int c = 0; c < recordingChannels; c++) { WaveTrack *newTrack = p->GetTrackFactory()->NewWaveTrack(); int initialheight = newTrack->GetHeight(); newTrack->SetOffset(t0); if (recordingChannels <= 2) { newTrack->SetHeight(initialheight/recordingChannels); } else { newTrack->SetMinimized(true); } if (recordingChannels == 2) { if (c == 0) { newTrack->SetChannel(Track::LeftChannel); newTrack->SetLinked(true); } else { newTrack->SetChannel(Track::RightChannel); newTrack->SetTeamed(true); } } else { newTrack->SetChannel( Track::MonoChannel ); } newRecordingTracks.Add(newTrack); } // msmeyer: StartStream calls a callback which triggers auto-save, so // we add the tracks where recording is done into now. We remove them // later if starting the stream fails for (unsigned int i = 0; i < newRecordingTracks.GetCount(); i++) t->Add(newRecordingTracks[i]); } int token = gAudioIO->StartStream(playbackTracks, newRecordingTracks, /* REQUIRES PORTMIDI */ // midiTracks, t->GetTimeTrack(), p->GetRate(), t0, t1, p); bool success = (token != 0); if (success) { p->SetAudioIOToken(token); mBusyProject = p; SetVUMeters(p); } else { // msmeyer: Delete recently added tracks if opening stream fails if (!shifted) { for (unsigned int i = 0; i < newRecordingTracks.GetCount(); i++) { t->Remove(newRecordingTracks[i]); delete newRecordingTracks[i]; } } // msmeyer: Show error message if stream could not be opened wxMessageBox(_("Error while opening sound device. " wxT("Please check the input device settings and the project sample rate.")), _("Error"), wxOK | wxICON_EXCLAMATION, this); SetPlay(false); SetStop(false); SetRecord(false); } } }