22#include <wx/wxcrtvararg.h>
29#include "../lib-src/header-substitutes/allegro.h"
33#define ROUND(x) ((int) ((x) + 0.5))
51#define SON_AutoSave 67
52#define SON_ModifyState 60
53#define SON_NoteBackground 72
54#define SON_NoteForeground 74
55#define SON_Measures 76
56#define SON_Serialize 77
57#define SON_Unserialize 79
62bool sonificationStarted =
false;
66 PmError err = Pm_OpenOutput(&sonMidiStream, Pm_GetDefaultOutputDeviceID(),
67 NULL, 0, NULL, NULL, 0);
68 if (err) sonMidiStream = NULL;
70 Pm_WriteShort(sonMidiStream, 0, Pm_Message(0xC0, SON_PROGRAM, 0));
71 sonificationStarted =
true;
77 if (sonMidiStream) Pm_Close(sonMidiStream);
78 sonificationStarted =
false;
84void SonifyNoteOnOff(
int p,
int v)
86 if (!sonificationStarted)
89 Pm_WriteShort(sonMidiStream, 0, Pm_Message(0x90, p, v));
93 void SonifyBegin ## name() { SonifyNoteOnOff(SON_ ## name, SON_VEL); } \
94 void SonifyEnd ## name() { SonifyNoteOnOff(SON_ ## name, 0); }
118 auto result = tracks.Add( std::make_shared<NoteTrack>());
119 result->AttachedTrackObjects::BuildAll();
143 mSeq = std::make_unique<Alg_seq>();
145 std::unique_ptr<Alg_track> alg_track
146 { Alg_seq::unserialize
148 wxASSERT(alg_track->get_type() ==
's');
149 mSeq.reset(
static_cast<Alg_seq*
>(alg_track.release()) );
163 auto duplicate = std::make_shared<NoteTrack>();
164 duplicate->Init(*
this);
173 mSeq->serialize(&buffer,
174 &duplicate->mSerializationLength);
175 duplicate->mSerializationBuffer.reset( (
char*)buffer );
182 duplicate->mSerializationBuffer.reset
184 memcpy( duplicate->mSerializationBuffer.get(),
185 this->mSerializationBuffer.get(), this->mSerializationLength );
195#ifdef EXPERIMENTAL_MIDI_OUT
196 duplicate->SetVelocity(GetVelocity());
223 seq.convert_to_seconds();
226 if (t1 > seq.get_dur()) {
228 if (t0 >= t1)
return;
230 Alg_iterator iter(
mSeq.get(),
false);
233 while (0 != (event = iter.next()) && event->time < t1) {
234 if (event->is_note() && event->time >= t0) {
235 event->set_pitch(event->get_pitch() + semitones);
240 seq.convert_to_beats();
241 Alg_time_map_ptr map = seq.get_time_map();
242 map->insert_beat(t0, map->time_to_beat(t0));
243 map->insert_beat(t1, map->time_to_beat(t1));
244 int i, len = map->length();
245 for (i = 0; i < len; i++) {
246 Alg_beat &beat = map->beats[i];
247 beat.time = warper.
Warp(beat.time + offset) - offset;
250 seq.convert_to_seconds();
256(
const NoteTrack *pTrack, wxDC & dc,
const wxRect &rect,
int highlightedChannel )
259 wxASSERT_MSG(rect.width % 4 == 0,
"Midi channel control rect width must be divisible by 4");
260 wxASSERT_MSG(rect.height % 4 == 0,
"Midi channel control rect height must be divisible by 4");
262 auto cellWidth = rect.width / 4;
263 auto cellHeight = rect.height / 4;
266 for (
int row = 0; row < 4; row++) {
267 for (
int col = 0; col < 4; col++) {
270 int chanName = row * 4 + col + 1;
272 box.x = rect.x + col * cellWidth;
273 box.y = rect.y + row * cellHeight;
274 box.width = cellWidth;
275 box.height = cellHeight;
277 bool visible = pTrack ? pTrack->
IsVisibleChan(chanName - 1) :
true;
280 if ( chanName == highlightedChannel + 1 )
284 dc.DrawRectangle(box);
288#define CHANNEL_ON_IS_DOWN 1
289#if CHANNEL_ON_IS_DOWN
294 AColor::Line(dc, box.x, box.y, box.x + box.width - 1, box.y);
295 AColor::Line(dc, box.x, box.y, box.x, box.y + box.height - 1);
297#if CHANNEL_ON_IS_DOWN
303 box.x + box.width - 1, box.y,
304 box.x + box.width - 1, box.y + box.height - 1);
306 box.x, box.y + box.height - 1,
307 box.x + box.width - 1, box.y + box.height - 1);
309 if ( chanName == highlightedChannel + 1 )
313 dc.DrawRectangle(box);
314#if CHANNEL_ON_IS_DOWN
319 AColor::Line(dc, box.x, box.y, box.x + box.width - 1, box.y);
320 AColor::Line(dc, box.x, box.y, box.x, box.y + box.height - 1);
322#if CHANNEL_ON_IS_DOWN
328 box.x + box.width - 1, box.y,
329 box.x + box.width - 1, box.y + box.height - 1);
331 box.x, box.y + box.height - 1,
332 box.x + box.width - 1, box.y + box.height - 1);
340 text.Printf(wxT(
"%d"), chanName);
341 dc.GetTextExtent(text, &w, &h);
343 dc.DrawText(text, box.x + (box.width - w) / 2, box.y + (box.height - h) / 2);
352 wxASSERT_MSG(rect.width % 4 == 0,
"Midi channel control rect width must be divisible by 4");
353 wxASSERT_MSG(rect.height % 4 == 0,
"Midi channel control rect height must be divisible by 4");
355 auto cellWidth = rect.width / 4;
356 auto cellHeight = rect.height / 4;
358 int col = (mx - rect.x) / cellWidth;
359 int row = (my - rect.y) / cellHeight;
361 return row * 4 + col;
382 mSeq = std::move(seq);
389 debugOutput = fopen(
"debugOutput.txt",
"wt");
390 wxFprintf(debugOutput,
"Importing MIDI...\n");
397 while(i < mSeq->length()) {
398 wxFprintf(debugOutput,
"--\n");
399 wxFprintf(debugOutput,
"type: %c\n",
400 ((Alg_event_ptr)
mSeq->track_list.tracks[i])->get_type());
401 wxFprintf(debugOutput,
"time: %f\n",
402 ((Alg_event_ptr)
mSeq->track_list.tracks[i])->time);
403 wxFprintf(debugOutput,
"channel: %li\n",
404 ((Alg_event_ptr)
mSeq->track_list.tracks[i])->chan);
406 if(((Alg_event_ptr)
mSeq->track_list.tracks[i])->get_type() == wxT(
'n'))
408 wxFprintf(debugOutput,
"pitch: %f\n",
409 ((Alg_note_ptr)
mSeq->track_list.tracks[i])->pitch);
410 wxFprintf(debugOutput,
"duration: %f\n",
411 ((Alg_note_ptr)
mSeq->track_list.tracks[i])->dur);
412 wxFprintf(debugOutput,
"velocity: %f\n",
413 ((Alg_note_ptr)
mSeq->track_list.tracks[i])->loud);
415 else if(((Alg_event_ptr)
mSeq->track_list.tracks[i])->get_type() == wxT(
'n'))
417 wxFprintf(debugOutput,
"key: %li\n", ((Alg_update_ptr)
mSeq->track_list.tracks[i])->get_identifier());
418 wxFprintf(debugOutput,
"attribute type: %c\n", ((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.attr_type());
419 wxFprintf(debugOutput,
"attribute: %s\n", ((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.attr_name());
421 if(((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.attr_type() == wxT(
'r'))
423 wxFprintf(debugOutput,
"value: %f\n", ((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.r);
425 else if(((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.attr_type() == wxT(
'i')) {
426 wxFprintf(debugOutput,
"value: %li\n", ((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.i);
428 else if(((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.attr_type() == wxT(
's')) {
429 wxFprintf(debugOutput,
"value: %s\n", ((Alg_update_ptr)
mSeq->track_list.tracks[i])->parameter.s);
438 wxFprintf(debugOutput,
"No sequence defined!\n");
454 auto newTrack = std::make_shared<NoteTrack>();
456 newTrack->Init(*
this);
459 seq.convert_to_seconds();
460 newTrack->mSeq.reset(seq.cut(t0 -
GetOffset(), len,
false));
461 newTrack->SetOffset(0);
481 auto newTrack = std::make_shared<NoteTrack>();
483 newTrack->Init(*
this);
486 seq.convert_to_seconds();
487 newTrack->mSeq.reset(seq.copy(t0 -
GetOffset(), len,
false));
488 newTrack->SetOffset(0);
506 seq.convert_to_seconds();
508 seq.clear(t1 -
GetOffset(), seq.get_dur() + 10000.0,
false);
531 auto start = t0 - offset;
536 seq.clear(0, len + start,
false);
546 seq.clear(start, len,
false);
577 auto offset = other->GetOffset();
579 seq.convert_to_seconds();
580 seq.insert_silence( t -
GetOffset(), offset );
592 seq.paste(t -
GetOffset(), &other->GetSeq());
612 seq.convert_to_seconds();
616 seq.silence(t0 -
GetOffset(), len,
false);
625 seq.convert_to_seconds();
626 seq.insert_silence(t -
GetOffset(), len);
632#ifdef EXPERIMENTAL_MIDI_OUT
633void NoteTrack::SetVelocity(
float velocity)
635 if (GetVelocity() != velocity) {
636 DoSetVelocity(velocity);
641void NoteTrack::DoSetVelocity(
float velocity)
643 mVelocity.store(velocity, std::memory_order_relaxed);
654 seq.convert_to_beats();
656 double tempo = seq.get_tempo(0.0);
657 double beats_per_measure = seq.get_bar_len(0.0);
658 int m =
ROUND(t * tempo / beats_per_measure);
662 tempo = beats_per_measure * m / t;
663 seq.insert_silence(0.0, beats_per_measure * m);
664 seq.set_tempo(tempo * 60.0 , 0.0, beats_per_measure * m);
665 seq.write(
"afterShift.gro");
668 seq.convert_to_seconds();
669 seq.clear(0, t,
true);
682 seq_time = seq.nearest_beat_time(seq_time, &beat);
690 {
"note",
"midi",
XO(
"Note Track") },
true,
707 auto pNewTrack = std::make_shared<NoteTrack>();
708 pNewTrack->Init(*
this);
709 pNewTrack->Paste(0.0,
this);
723 results.emplace_back( GetStartTime(), GetEndTime() );
732 seq.set_real_dur( seq.get_real_dur() + delta );
734 seq.convert_to_seconds();
735 seq.set_dur( seq.get_dur() + delta );
743 bool result = seq.stretch_region( t0.second, t1.second, newDur );
745 const auto oldDur = t1.first - t0.first;
753 void swap(std::unique_ptr<Alg_seq> &a, std::unique_ptr<Alg_seq> &b)
755 std::unique_ptr<Alg_seq> tmp = std::move(a);
768 double start = -offset;
769 if (start < 0) start = 0;
772 cleanup.reset(
GetSeq().copy(start,
GetSeq().get_dur() - start,
false) );
773 auto seq = cleanup.get();
778 auto cleanup2 =
finally( [&] {
swap( this->
mSeq, cleanup ); } );
785 double beats_per_measure = 4.0;
786 Alg_time_sig_ptr tsp = NULL;
787 if (seq->time_sig.length() > 0 && seq->time_sig[0].beat < ALG_EPS) {
789 tsp = &(seq->time_sig[0]);
790 beats_per_measure = (tsp->num * 4) / tsp->den;
793 double bps = ALG_DEFAULT_BPM / 60;
794 Alg_time_map_ptr map = seq->get_time_map();
795 Alg_beat_ptr bp = &(map->beats[0]);
796 if (bp->time < ALG_EPS) {
797 if (map->beats.len > 1) {
798 bps = (map->beats[1].beat - map->beats[0].beat) /
799 (map->beats[1].time - map->beats[0].time);
800 }
else if (seq->get_time_map()->last_tempo_flag) {
801 bps = seq->get_time_map()->last_tempo;
806 double measure_time = beats_per_measure / bps;
807 int n =
ROUND(offset / measure_time);
810 measure_time = offset / n;
811 bps = beats_per_measure / measure_time;
813 seq->convert_to_beats();
814 seq->insert_silence(0, beats_per_measure * n);
817 seq->set_time_sig(0, tsp->num, tsp->den);
820 seq->set_tempo(bps * 60.0, 0, beats_per_measure * n);
830 double beat = mySeq.get_time_map()->time_to_beat(start);
832 int i = mySeq.time_sig.find_beat(beat);
837 if (mySeq.time_sig.length() > 0 &&
838 within(beat, mySeq.time_sig[i].beat, ALG_EPS)) {
843 }
else if (i == 0 && (mySeq.time_sig.length() == 0 ||
844 mySeq.time_sig[i].beat > beat)) {
847 double measures = beat / 4.0;
848 double imeasures =
ROUND(measures);
849 if (!
within(measures, imeasures, ALG_EPS)) {
850 double bar_offset = ((int)(measures) + 1) * 4.0 - beat;
851 seq->set_time_sig(bar_offset, 4, 4);
861 Alg_time_sig_ptr tsp = &(mySeq.time_sig[i]);
862 double beats_per_measure = (tsp->num * 4) / tsp->den;
863 double measures = (beat - tsp->beat) / beats_per_measure;
864 int imeasures =
ROUND(measures);
865 if (!
within(measures, imeasures, ALG_EPS)) {
869 double bar = tsp->beat + beats_per_measure * ((int)(measures) + 1);
870 double bar_offset = bar - beat;
874 seq->set_time_sig(bar_offset, tsp->num, tsp->den);
886 std::unique_ptr<Alg_seq> cleanup;
888 bool rslt = seq->smf_write(f.mb_str());
898 seq.convert_to_seconds();
900 seq.convert_to_beats();
902 return seq.write(f.mb_str(), offset);
909 return (nValue >= 0 && nValue < (1 << 16));
915 if (tag ==
"notetrack") {
916 for (
auto pair : attrs)
918 auto attr = pair.first;
919 auto value = pair.second;
927 else if (attr ==
"offset" && value.TryGet(dblValue))
929 else if (attr ==
"visiblechannels") {
930 if (!value.TryGet(nValue) ||
935#ifdef EXPERIMENTAL_MIDI_OUT
936 else if (attr ==
"velocity" && value.TryGet(dblValue))
937 DoSetVelocity(
static_cast<float>(dblValue));
939 else if (attr ==
"bottomnote" && value.TryGet(nValue))
941 else if (attr ==
"topnote" && value.TryGet(nValue))
943 else if (attr ==
"data") {
944 std::string s(value.ToWString());
945 std::istringstream data(s);
946 mSeq = std::make_unique<Alg_seq>(data,
false);
962 std::ostringstream data;
969 saveme =
static_cast<NoteTrack*
>(holder.get());
971 saveme->
GetSeq().write(data,
true);
972 xmlFile.StartTag(wxT(
"notetrack"));
973 saveme->Track::WriteCommonXMLAttributes( xmlFile );
975 xmlFile.WriteAttr(wxT(
"offset"), saveme->
GetOffset());
976 xmlFile.WriteAttr(wxT(
"visiblechannels"),
979#ifdef EXPERIMENTAL_MIDI_OUT
980 xmlFile.WriteAttr(wxT(
"velocity"),
981 static_cast<double>(saveme->GetVelocity()));
983 xmlFile.WriteAttr(wxT(
"bottomnote"), saveme->
mBottomNote);
984 xmlFile.WriteAttr(wxT(
"topnote"), saveme->
mTopNote);
985 xmlFile.WriteAttr(wxT(
"data"), wxString(data.str().c_str(), wxConvUTF8));
986 xmlFile.EndTag(wxT(
"notetrack"));
1023 if (note2 < note1) {
auto tmp = note1; note1 = note2; note2 = tmp; }
1040void NoteTrack::StartVScroll()
1045void NoteTrack::VScroll(
int start,
int end)
1047 int ph = GetPitchHeight();
1048 int delta = ((
end - start) + ph / 2) / ph;
1058 int newExtent = (int) (extent / multiplier);
1067 int newBottomNote = clickedPitch - (newExtent * position);
1068 int newTopNote = clickedPitch + (newExtent * (1 - position));
1075 wxRect trackRect(0, rect.GetY(), 1, rect.GetHeight());
1079 if (pitch1 == pitch2) {
1081 Zoom(rect, start, 1,
true);
1090 Alg_iterator iterator( &
GetSeq(),
false );
1095 bool hasNotes =
false;
1099 while (NULL != (evt = iterator.next())) {
1100 if (evt->is_note()) {
1101 int pitch = (int) evt->get_pitch();
1103 if (pitch < minPitch)
1105 if (pitch > maxPitch)
1123 mMargin =
std::min((
int) (r.height / (
float)(span)) / 2, r.height / 4);
1126 int numC = 0, numF = 0;
1129 if (topOctave == botOctave)
1131 if (botNote == 0) numC = 1;
1132 if (topNote <= 5) numF = 1;
1136 numC = topOctave - botOctave;
1137 numF = topOctave - botOctave - 1;
1138 if (botNote == 0) numC++;
1139 if (botNote <= 5) numF++;
1140 if (topOctave <= 5) numF++;
1143 auto effectiveHeight = r.height - (2 * (
mMargin + 1)) - numC - numF;
1175#include <wx/sstream.h>
1176#include <wx/txtstrm.h>
1178#include "portmidi.h"
1183 wxStringOutputStream o;
1184 wxTextOutputStream s(o, wxEOL_UNIX);
1187 return XO(
"Stream is active ... unable to gather information.\n")
1193 int recDeviceNum = Pm_GetDefaultInputDeviceID();
1194 int playDeviceNum = Pm_GetDefaultOutputDeviceID();
1195 int cnt = Pm_CountDevices();
1198 wxLogDebug(wxT(
"PortMidi reports %d MIDI devices"), cnt);
1200 s << wxT(
"==============================\n");
1201 s <<
XO(
"Default recording device number: %d\n").Format( recDeviceNum );
1202 s <<
XO(
"Default playback device number: %d\n").Format( playDeviceNum );
1209 s <<
XO(
"No devices found\n");
1210 return o.GetString();
1213 for (
int i = 0; i < cnt; i++) {
1214 s << wxT(
"==============================\n");
1216 const PmDeviceInfo* info = Pm_GetDeviceInfo(i);
1218 s <<
XO(
"Device info unavailable for: %d\n").Format( i );
1222 wxString
name = wxSafeConvertMB2WX(info->name);
1223 wxString hostName = wxSafeConvertMB2WX(info->interf);
1225 s <<
XO(
"Device ID: %d\n").Format( i );
1226 s <<
XO(
"Device name: %s\n").Format(
name );
1227 s <<
XO(
"Host name: %s\n").Format( hostName );
1229 s <<
XO(
"Supports output: %d\n").Format( info->output );
1231 s <<
XO(
"Supports input: %d\n").Format( info->input );
1232 s <<
XO(
"Opened: %d\n").Format( info->opened );
1234 if (
name == playDevice && info->output)
1237 if (
name == recDevice && info->input)
1242 if (recDeviceNum < 0 && info->input){
1245 if (playDeviceNum < 0 && info->output){
1250 bool haveRecDevice = (recDeviceNum >= 0);
1251 bool havePlayDevice = (playDeviceNum >= 0);
1253 s << wxT(
"==============================\n");
1255 s <<
XO(
"Selected MIDI recording device: %d - %s\n").Format( recDeviceNum, recDevice );
1257 s <<
XO(
"No MIDI recording device found for '%s'.\n").Format( recDevice );
1260 s <<
XO(
"Selected MIDI playback device: %d - %s\n").Format( playDeviceNum, playDevice );
1262 s <<
XO(
"No MIDI playback device found for '%s'.\n").Format( playDevice );
1268 s << wxT(
"==============================\n");
1269#ifdef EXPERIMENTAL_MIDI_OUT
1270 s << wxT(
"EXPERIMENTAL_MIDI_OUT is enabled\n");
1272 s << wxT(
"EXPERIMENTAL_MIDI_OUT is NOT enabled\n");
1274#ifdef EXPERIMENTAL_MIDI_IN
1275 s << wxT(
"EXPERIMENTAL_MIDI_IN is enabled\n");
1277 s << wxT(
"EXPERIMENTAL_MIDI_IN is NOT enabled\n");
1282 return o.GetString();
const TranslatableString name
MessageBoxException for violation of preconditions or assertions.
#define THROW_INCONSISTENCY_EXCEPTION
Throw InconsistencyException, using C++ preprocessor to identify the source code location.
IntSetting MIDISynthLatency_ms
StringSetting MIDIRecordingDevice
static ProjectFileIORegistry::ObjectReaderEntry readerEntry
wxString GetMIDIDeviceInfo()
StringSetting MIDIPlaybackDevice
static const Track::TypeInfo & typeInfo()
#define SonifyEndSerialize()
#define SonifyBeginSerialize()
#define SonifyEndSonification()
#define SonifyBeginSonification()
std::pair< double, double > QuantizedTimeAndBeat
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
bool within(A a, B b, DIST d)
std::vector< Attribute > AttributesList
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
static void LightMIDIChannel(wxDC *dc, int channel)
static void MIDIChannel(wxDC *dc, int channel)
static void DarkMIDIChannel(wxDC *dc, int channel)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static AudioIOBase * Get()
Track subclass holding data representing sound (as notes, or samples, or ...)
bool HandleXMLAttribute(const std::string_view &, const XMLAttributeValueView &)
void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const
static EnumSetting< bool > AllegroStyleSetting
Specialization of Setting for int.
Data used to display a note track.
int GetPitchHeight(int factor) const
int GetNotePos(int p) const
int GetOctaveHeight() const
NoteTrackDisplayData(const NoteTrack *track, const wxRect &r)
int GetNoteMargin() const
int YToIPitch(int y) const
int IPitchToY(int p) const
A Track that is used for Midi notes. (Somewhat old code).
void SetSequence(std::unique_ptr< Alg_seq > &&seq)
const TypeInfo & GetTypeInfo() const override
static const TypeInfo & ClassTypeInfo()
ConstIntervals GetIntervals() const override
Report times on the track where important intervals begin and end, for UI to snap to.
bool ExportAllegro(const wxString &f) const
Track::Holder Cut(double t0, double t1) override
void SetNoteRange(int note1, int note2)
Sets the top and bottom note (both pitches) automatically, swapping them if needed.
void AddToDuration(double delta)
std::unique_ptr< char[]> mSerializationBuffer
void Paste(double t, const Track *src) override
double GetOffset() const override
bool ExportMIDI(const wxString &f) const
bool IsVisibleChan(int c) const
void SetVisibleChannels(unsigned value)
void WriteXML(XMLWriter &xmlFile) const override
double GetEndTime() const override
int FindChannel(const wxRect &rect, int mx, int my)
static void DrawLabelControls(const NoteTrack *pTrack, wxDC &dc, const wxRect &rect, int highlightedChannel=-1)
void ShiftNoteRange(int offset)
Shifts all notes vertically by the given pitch.
std::unique_ptr< Alg_seq > mSeq
void InsertSilence(double t, double len) override
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
bool StretchRegion(QuantizedTimeAndBeat t0, QuantizedTimeAndBeat t1, double newDur)
Alg_seq * MakeExportableSeq(std::unique_ptr< Alg_seq > &cleanup) const
void ZoomAllNotes()
Zooms so that all notes are visible.
static NoteTrack * New(AudacityProject &project)
void SetTopNote(int note)
Sets the top note (a pitch), making sure that it is never less than the bottom note.
unsigned GetVisibleChannels() const
QuantizedTimeAndBeat NearestBeatTime(double time) const
void Zoom(const wxRect &rect, int y, float multiplier, bool center)
void WarpAndTransposeNotes(double t0, double t1, const TimeWarper &warper, double semitones)
void ZoomTo(const wxRect &rect, int start, int end)
void ToggleVisibleChan(int c)
bool Trim(double t0, double t1)
void SoloVisibleChan(int c)
Track::Holder Clone() const override
Track::Holder PasteInto(AudacityProject &) const override
Find or create the destination track for a paste, maybe in a different project.
double GetStartTime() const override
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
void SetBottomNote(int note)
Sets the bottom note (a pitch), making sure that it is never greater than the top note.
int GetBottomNote() const
Gets the current bottom note (a pitch)
static const float ZoomStep
int GetTopNote() const
Gets the current top note (a pitch)
void Clear(double t0, double t1) override
long mSerializationLength
bool LabelClick(const wxRect &rect, int x, int y, bool right)
void Silence(double t0, double t1) override
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
static const TypeInfo & ClassTypeInfo()
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined */
Specialization of Setting for strings.
wxColour & Colour(int iIndex)
Transforms one point in time to another point. For example, a time stretching effect might use one to...
virtual double Warp(double originalTime) const =0
Abstract base class for an object holding data associated with points on a time axis.
virtual void SetOffset(double o)
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
std::shared_ptr< Track > Holder
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
std::vector< Interval > Intervals
std::vector< ConstInterval > ConstIntervals
void SetName(const wxString &n)
static TrackList & Get(AudacityProject &project)
This class is an interface which should be implemented by classes which wish to be able to load and s...
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
bool IsValidVisibleChannels(const int nValue)
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)