📄 tonegen.cpp
字号:
/********************************************************************** Audacity: A Digital Audio Editor ToneGen.cpp Steve Jolly This class implements a tone generator effect.**********************************************************************/#include "ToneGen.h"#include "../WaveTrack.h"#include <wx/button.h>#include <wx/checkbox.h>#include <wx/choice.h>#include <wx/intl.h>#include <wx/sizer.h>#include <wx/stattext.h>#include <wx/textctrl.h>#include <wx/wxprec.h> //// EffectToneGen//EffectToneGen::EffectToneGen(){ frequency = float(440.0); //Hz waveform = 0; //sine amplitude = float(1.0); length = sDefaultGenerateLen;}wxString EffectToneGen::GetEffectDescription() { // Note: This is useful only after values have been set. const wxChar* waveformNames[] = {wxT("sine"), wxT("square"), wxT("sawtooth")}; return wxString::Format(_("Applied effect: Generate %s %s wave, frequency = %.2f Hz, amplitude = %.2f, %.6lf seconds"), this->GetEffectName().c_str(), waveformNames[waveform], frequency, amplitude, length); } bool EffectToneGen::PromptUser(){ if (mT1 > mT0) length = mT1 - mT0; ToneGenDialog dlog(mParent, -1, _("Tone Generator")); dlog.frequency = frequency; dlog.waveform = waveform; dlog.amplitude = amplitude; dlog.length = length; dlog.GetWaveformChoice()->Append(_("Sine")); dlog.GetWaveformChoice()->Append(_("Square")); dlog.GetWaveformChoice()->Append(_("Sawtooth")); dlog.TransferDataToWindow(); dlog.CentreOnParent(); dlog.ShowModal(); if (dlog.GetReturnCode() == 0) return false; frequency = dlog.frequency; waveform = dlog.waveform; amplitude = dlog.amplitude; length = dlog.length; return true;}bool EffectToneGen::TransferParameters( Shuttle & shuttle ){ // shuttle.TransferInt("",,0); return true;}bool EffectToneGen::MakeTone(float *buffer, sampleCount len){ double throwaway = 0; //passed to modf but never used int i; switch (waveform) { case 0: //sine for (i = 0; i < len; i++) buffer[i] = amplitude * (float) sin(2 * M_PI * (i + mSample) * frequency / mCurRate); mSample += len; break; case 1: //square for (i = 0; i < len; i++) { if (modf(((i + mSample) * frequency / mCurRate), &throwaway) < 0.5) buffer[i] = amplitude; else buffer[i] = -amplitude; } mSample += len; break; case 2: //sawtooth for (i = 0; i < len; i++) buffer[i] = 2 * amplitude * ((((i + mSample) % (int) (mCurRate / frequency)) / (mCurRate / frequency)) - 0.5); mSample += len; break; default: break; } return true;}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;}// WDR: class implementations//----------------------------------------------------------------------------// ToneGenDialog//----------------------------------------------------------------------------#define FREQ_MIN 1#define FREQ_MAX 20000#define AMP_MIN 0#define AMP_MAX 1#define WAVEFORM_MIN 0#define WAVEFORM_MAX 2BEGIN_EVENT_TABLE(ToneGenDialog, wxDialog) EVT_BUTTON(wxID_OK, ToneGenDialog::OnCreateTone) EVT_BUTTON(wxID_CANCEL, ToneGenDialog::OnCancel)END_EVENT_TABLE()ToneGenDialog::ToneGenDialog(wxWindow * parent, wxWindowID id, const wxString & title, const wxPoint & position, const wxSize & size, long style):wxDialog(parent, id, title, position, size, style){ CreateToneGenDialog(this, TRUE);}bool ToneGenDialog::Validate(){ return TRUE;}bool ToneGenDialog::TransferDataToWindow(){ wxChoice *choice; wxTextCtrl *text; choice = GetWaveformChoice(); if (choice) choice->SetSelection(waveform); text = GetFreqText(); if (text) { wxString str; str.Printf(wxT("%.2f"), frequency); text->SetValue(str); } text = GetAmpText(); if (text) { wxString str; str.Printf(wxT("%.2f"), amplitude); text->SetValue(str); } text = GetLengthText(); if (text) { wxString str; str.Printf(wxT("%.6lf"), length); text->SetValue(str); } return TRUE;}bool ToneGenDialog::TransferDataFromWindow(){ wxTextCtrl *t; t = GetLengthText(); if (t) { t->GetValue().ToDouble(&length); } t = GetAmpText(); if (t) { double d; t->GetValue().ToDouble(&d); amplitude = TrapDouble(d, AMP_MIN, AMP_MAX); } t = GetFreqText(); if (t) { double d; t->GetValue().ToDouble(&d); frequency = TrapDouble(d, FREQ_MIN, FREQ_MAX); } wxChoice *c = GetWaveformChoice(); if (c) waveform = TrapLong(c->GetSelection(), WAVEFORM_MIN, WAVEFORM_MAX); return TRUE;}// WDR: handler implementations for ToneGenDialogvoid ToneGenDialog::OnCreateTone(wxCommandEvent & event){ TransferDataFromWindow(); if (Validate()) EndModal(true); else { event.Skip(); }}void ToneGenDialog::OnCancel(wxCommandEvent & event){ EndModal(false);}wxSizer *CreateToneGenDialog(wxWindow * parent, bool call_fit, bool set_sizer){ wxBoxSizer *item0 = new wxBoxSizer(wxVERTICAL); wxBoxSizer *item2 = new wxBoxSizer(wxHORIZONTAL); wxStaticText *item3 = new wxStaticText(parent, ID_TEXT, _("Waveform:"), wxDefaultPosition, wxDefaultSize, 0); item2->Add(item3, 0, wxALIGN_CENTRE | wxALL, 5); wxChoice *item4 = new wxChoice(parent, ID_WAVEFORM, wxDefaultPosition, wxSize(80, -1), 0, NULL, 0); item2->Add(item4, 0, wxALIGN_CENTRE | wxALL, 5); item0->Add(item2, 1, wxALIGN_CENTRE | wxALL, 5); wxBoxSizer *item5 = new wxBoxSizer(wxHORIZONTAL); wxStaticText *item6 = new wxStaticText(parent, ID_TEXT, _("Frequency / Hz"), wxDefaultPosition, wxDefaultSize, 0); item5->Add(item6, 0, wxALIGN_CENTRE | wxALL, 5); wxTextCtrl *item7 = new wxTextCtrl(parent, ID_FREQTEXT, wxT(""), wxDefaultPosition, wxSize(60, -1), 0); item5->Add(item7, 0, wxALIGN_CENTRE | wxALL, 5); item0->Add(item5, 1, wxALIGN_CENTRE | wxALL, 5); wxBoxSizer *item8 = new wxBoxSizer(wxHORIZONTAL); wxStaticText *item9 = new wxStaticText(parent, ID_TEXT, _("Amplitude (0-1)"), wxDefaultPosition, wxDefaultSize, 0); item8->Add(item9, 0, wxALIGN_CENTRE | wxALL, 5); wxTextCtrl *item10 = new wxTextCtrl(parent, ID_AMPTEXT, wxT(""), wxDefaultPosition, wxSize(60, -1), 0); item8->Add(item10, 0, wxALIGN_CENTRE | wxALL, 5); item0->Add(item8, 1, wxALIGN_CENTRE | wxALL, 5); item8 = new wxBoxSizer(wxHORIZONTAL); item9 = new wxStaticText(parent, ID_TEXT, _("Length (seconds)"), wxDefaultPosition, wxDefaultSize, 0); item8->Add(item9, 0, wxALIGN_CENTRE | wxALL, 5); item10 = new wxTextCtrl(parent, ID_LENGTHTEXT, wxT(""), wxDefaultPosition, wxSize(120, -1), 0); item8->Add(item10, 0, wxALIGN_CENTRE | wxALL, 5); item0->Add(item8, 1, wxALIGN_CENTRE | wxALL, 5); wxBoxSizer *item11 = new wxBoxSizer(wxHORIZONTAL); wxButton *item13 = new wxButton(parent, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0); item11->Add(item13, 0, wxALIGN_CENTRE | wxALL, 5); wxButton *item12 = new wxButton(parent, wxID_OK, _("Generate Tone"), wxDefaultPosition, wxDefaultSize, 0); item12->SetDefault(); item12->SetFocus(); item11->Add(item12, 0, wxALIGN_CENTRE | wxALL, 5); item0->Add(item11, 0, wxALIGN_CENTRE | wxALL, 5); if (set_sizer) { parent->SetAutoLayout(TRUE); parent->SetSizer(item0); if (call_fit) { item0->Fit(parent); item0->SetSizeHints(parent); } } return item0;}// Indentation settings for Vim and Emacs and unique identifier for Arch, a// version control system. Please do not modify past this point.//// Local Variables:// c-basic-offset: 3// indent-tabs-mode: nil// End://// vim: et sts=3 sw=3// arch-tag: 04ea2450-8127-45c4-8702-6aaf5b60ed8c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -