mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 15:49:41 +02:00
A subset of the original v4 patch (which will become v5 eventually)
The main operational difference is that for v4 effect onward, the sound name will now be *TRACK*. This will not affect existing effects since they use version number 3 or less. This also provides the Nyquist effect with much more information about the current processing: Variable Property What *AUDACITY* VERSION current Audacity version number *SYSTEM-DIR* BASE Audacity install path *SYSTEM-DIR* DATA Audacity data path *SYSTEM-DIR* HELP Audacity help path *SYSTEM-DIR* TEMP Audacity temp file path *SYSTEM-DIR* PLUGIN Audacity search path for Nyquist plugins *PROJECT* RATE current project sample rate *PROJECT* TRACKS total number of tracks in the project *PROJECT* WAVETRACKS number of wave tracks in the project *PROJECT* LABELTRACKS number of label tracks in the project *PROJECT* MIDITRACKS number of midi tracks in the project *PROJECT* TIMETRACKS number of time tracks in the project *SELECTION* START start time of current selection *SELECTION* END end time of current selection *SELECTION* TRACKS number of tracks in the current selection *SELECTION* CHANNELS number of channels in the current selection *SELECTION* LOW-HZ low frequency from spectrogram (if available, else nil) *SELECTION* CENTER-HZ center frequence (calculated) (if available, else nil) *SELECTION* HIGH-HZ high frequence from spectrogram (if available, else nil) *SELECTION* BANDWIDTH bandwidth in octaves (calculated) (if available, else nil) *SELECTION* PEAK-LEVEL peak amplitude for the current selection *TRACK* INDEX 1-based index of track being processed *TRACK* NAME name of track *TRACK* TYPE type of track: wave, midi, label, time *TRACK* VIEW track view: Waveform, Waveform (dB), etc. *TRACK* CHANNELS number of channels in the track *TRACK* START-TIME start time of track *TRACK* END-TIME end time of track *TRACK* GAIN track gain *TRACK* PAN track pan *TRACK* RATE sample rate of track *TRACK* FORMAT sample format: 16 (int), 24 (int), 32.0 (float) *TRACK* CLIPS list of start/end times for clips for each channel
This commit is contained in:
parent
bce372bfee
commit
4c0aa60871
@ -75,6 +75,7 @@ LOCAL int nyx_first_time = 1;
|
||||
LOCAL LVAL nyx_obarray;
|
||||
LOCAL FLOTYPE nyx_warp_stretch;
|
||||
LOCAL long nyx_input_length = 0;
|
||||
LOCAL char *nyx_audio_name = NULL;
|
||||
|
||||
/* Suspension node */
|
||||
typedef struct nyx_susp_struct {
|
||||
@ -454,6 +455,7 @@ void nyx_init()
|
||||
argv[0] = "nyquist";
|
||||
xlisp_main_init(1, argv);
|
||||
|
||||
nyx_audio_name = NULL;
|
||||
nyx_os_cb = NULL;
|
||||
nyx_output_cb = NULL;
|
||||
|
||||
@ -505,7 +507,7 @@ void nyx_cleanup()
|
||||
|
||||
// Make sure the sound nodes can be garbage-collected. Sounds are EXTERN
|
||||
// nodes whose value does not get copied during a full copy of the obarray.
|
||||
setvalue(xlenter("S"), NIL);
|
||||
setvalue(xlenter(nyx_get_audio_name()), NIL);
|
||||
|
||||
// Free excess memory segments - does a gc()
|
||||
freesegs();
|
||||
@ -520,6 +522,11 @@ void nyx_cleanup()
|
||||
// Reset vars
|
||||
nyx_input_length = 0;
|
||||
|
||||
if (nyx_audio_name) {
|
||||
free(nyx_audio_name);
|
||||
nyx_audio_name = NULL;
|
||||
}
|
||||
|
||||
#if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS
|
||||
printf("\nnyx_cleanup\n");
|
||||
xmem();
|
||||
@ -587,6 +594,25 @@ void nyx_capture_output(nyx_output_callback callback, void *userdata)
|
||||
nyx_output_ud = userdata;
|
||||
}
|
||||
|
||||
char *nyx_get_audio_name()
|
||||
{
|
||||
if (!nyx_audio_name) {
|
||||
nyx_audio_name = strdup("S");
|
||||
}
|
||||
|
||||
return nyx_audio_name;
|
||||
}
|
||||
|
||||
void nyx_set_audio_name(const char *name)
|
||||
{
|
||||
if (nyx_audio_name) {
|
||||
free(nyx_audio_name);
|
||||
nyx_audio_name = NULL;
|
||||
}
|
||||
|
||||
nyx_audio_name = strdup(name);
|
||||
}
|
||||
|
||||
void nyx_set_audio_params(double rate, long len)
|
||||
{
|
||||
LVAL flo;
|
||||
@ -670,7 +696,7 @@ void nyx_set_input_audio(nyx_audio_callback callback,
|
||||
}
|
||||
}
|
||||
|
||||
setvalue(xlenter("S"), val);
|
||||
setvalue(xlenter(nyx_get_audio_name()), val);
|
||||
|
||||
xlpop();
|
||||
}
|
||||
@ -862,7 +888,7 @@ nyx_rval nyx_eval_expression(const char *expr_string)
|
||||
|
||||
xlpop(); // unprotect expr
|
||||
|
||||
setvalue(xlenter("S"), NIL);
|
||||
setvalue(xlenter(nyx_get_audio_name()), NIL);
|
||||
|
||||
gc();
|
||||
|
||||
|
@ -61,6 +61,9 @@ extern "C"
|
||||
void *userdata,
|
||||
int num_channels,
|
||||
long len, double rate);
|
||||
|
||||
char *nyx_get_audio_name();
|
||||
void nyx_set_audio_name(const char *name);
|
||||
|
||||
nyx_rval nyx_eval_expression(const char *expr);
|
||||
|
||||
|
@ -31,8 +31,7 @@ void LoadNyquistEffect(wxString fname)
|
||||
|
||||
void LoadNyquistPlugins()
|
||||
{
|
||||
wxArrayString audacityPathList = wxGetApp().audacityPathList;
|
||||
wxArrayString pathList;
|
||||
wxArrayString pathList = EffectNyquist::GetNyquistSearchPath();
|
||||
wxArrayString files;
|
||||
unsigned int i;
|
||||
|
||||
@ -41,16 +40,6 @@ void LoadNyquistPlugins()
|
||||
EffectManager::Get().RegisterEffect(effect);
|
||||
|
||||
// Load .ny plug-ins
|
||||
for(i=0; i<audacityPathList.GetCount(); i++) {
|
||||
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("nyquist"),
|
||||
pathList);
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("plugins"),
|
||||
pathList);
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("plug-ins"),
|
||||
pathList);
|
||||
}
|
||||
|
||||
wxGetApp().FindFilesInPathList(wxT("*.ny"), pathList, files);
|
||||
#ifdef __WXGTK__
|
||||
wxGetApp().FindFilesInPathList(wxT("*.NY"), pathList, files); // Ed's fix for bug 179
|
||||
|
@ -50,9 +50,13 @@ effects from this one class.
|
||||
#include <wx/choice.h>
|
||||
|
||||
#include "../../AudacityApp.h"
|
||||
#include "../../LabelTrack.h"
|
||||
#include "../../FileNames.h"
|
||||
#include "../../Internat.h"
|
||||
#include "../../LabelTrack.h"
|
||||
#include "../../Project.h"
|
||||
#include "../../ShuttleGui.h"
|
||||
#include "../../WaveClip.h"
|
||||
#include "../../WaveTrack.h"
|
||||
#include "../../widgets/valnum.h"
|
||||
|
||||
#include "Nyquist.h"
|
||||
@ -83,6 +87,8 @@ EffectNyquist::EffectNyquist(wxString fName)
|
||||
mIsSal = false;
|
||||
mOK = false;
|
||||
|
||||
mVersion = 4;
|
||||
|
||||
mStop = false;
|
||||
mBreak = false;
|
||||
mCont = false;
|
||||
@ -259,12 +265,16 @@ void EffectNyquist::Parse(wxString line)
|
||||
// We support versions 1, 2 and 3
|
||||
// (Version 2 added support for string parameters.)
|
||||
// (Version 3 added support for choice parameters.)
|
||||
// (Version 4 added support for project/track/selection information.)
|
||||
if (len >= 2 && tokens[0] == wxT("version")) {
|
||||
if (tokens[1] != wxT("1") && tokens[1] != wxT("2") && tokens[1] != wxT("3")) {
|
||||
long v;
|
||||
tokens[1].ToLong(&v);
|
||||
if (v < 1 && v > 4) {
|
||||
// This is an unsupported plug-in version
|
||||
mOK = false;
|
||||
return;
|
||||
}
|
||||
mVersion = (int) v;
|
||||
}
|
||||
|
||||
if (len >= 2 && tokens[0] == wxT("name")) {
|
||||
@ -682,8 +692,114 @@ bool EffectNyquist::Process()
|
||||
mBreak = false;
|
||||
mCont = false;
|
||||
|
||||
mTrackIndex = 0;
|
||||
|
||||
mDebugOutput = "";
|
||||
|
||||
if (mVersion >= 4)
|
||||
{
|
||||
AudacityProject *project = GetActiveProject();
|
||||
|
||||
mProps = wxEmptyString;
|
||||
|
||||
mProps += wxString::Format(wxT("(putprop '*AUDACITY* (list %d %d %d) 'VERSION)\n"), AUDACITY_VERSION, AUDACITY_RELEASE, AUDACITY_REVISION);
|
||||
|
||||
mProps += wxString::Format(wxT("(putprop '*SYSTEM-DIR* \"%s\" 'BASE)\n"), FileNames::BaseDir().c_str());
|
||||
mProps += wxString::Format(wxT("(putprop '*SYSTEM-DIR* \"%s\" 'DATA)\n"), FileNames::DataDir().c_str());
|
||||
mProps += wxString::Format(wxT("(putprop '*SYSTEM-DIR* \"%s\" 'HELP)\n"), FileNames::HtmlHelpDir().RemoveLast().c_str());
|
||||
mProps += wxString::Format(wxT("(putprop '*SYSTEM-DIR* \"%s\" 'TEMP)\n"), FileNames::TempDir().c_str());
|
||||
|
||||
wxArrayString paths = EffectNyquist::GetNyquistSearchPath();
|
||||
wxString list;
|
||||
for (size_t i = 0, cnt = paths.GetCount(); i < cnt; i++)
|
||||
{
|
||||
list += wxT("\"") + paths[i] + wxT("\" ");
|
||||
}
|
||||
mProps += wxString::Format(wxT("(putprop '*SYSTEM-DIR* (list %s) 'PLUGIN)\n"), list.RemoveLast().c_str());
|
||||
|
||||
TrackListIterator all(project->GetTracks());
|
||||
Track *t;
|
||||
int numTracks = 0;
|
||||
int numWave = 0;
|
||||
int numLabel = 0;
|
||||
int numMidi = 0;
|
||||
int numTime = 0;
|
||||
for (t = all.First(); t; t = all.Next())
|
||||
{
|
||||
switch (t->GetKind())
|
||||
{
|
||||
case Track::Wave: numWave++; break;
|
||||
case Track::Label: numLabel++; break;
|
||||
#if defined(USE_MIDI)
|
||||
case Track::Note: numMidi++; break;
|
||||
#endif
|
||||
case Track::Time: numTime++; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
numTracks++;
|
||||
if (t->GetLinked())
|
||||
{
|
||||
all.Next();
|
||||
}
|
||||
}
|
||||
|
||||
mProps += wxString::Format(wxT("(putprop '*PROJECT* (float %g) 'RATE)\n"), project->GetRate());
|
||||
mProps += wxString::Format(wxT("(putprop '*PROJECT* %d 'TRACKS)\n"), numTracks);
|
||||
mProps += wxString::Format(wxT("(putprop '*PROJECT* %d 'WAVETRACKS)\n"), numWave);
|
||||
mProps += wxString::Format(wxT("(putprop '*PROJECT* %d 'LABELTRACKS)\n"), numLabel);
|
||||
mProps += wxString::Format(wxT("(putprop '*PROJECT* %d 'MIDITRACKS)\n"), numMidi);
|
||||
mProps += wxString::Format(wxT("(putprop '*PROJECT* %d 'TIMETRACKS)\n"), numTime);
|
||||
|
||||
SelectedTrackListOfKindIterator sel(Track::Wave, mOutputTracks);
|
||||
int numChannels = 0;
|
||||
numTracks = 0;
|
||||
for (WaveTrack *t = (WaveTrack *) sel.First(); t; t = (WaveTrack *) sel.Next()) {
|
||||
numTracks++;
|
||||
numChannels++;
|
||||
if (mT1 >= mT0) {
|
||||
if (t->GetLinked()) {
|
||||
numChannels++;
|
||||
sel.Next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* (float %g) 'START)\n"), mT0);
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* (float %g) 'END)\n"), mT1);
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* %d 'TRACKS)\n"), numTracks);
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* %d 'CHANNELS)\n"), numChannels);
|
||||
|
||||
wxString lowHz = wxT("nil");
|
||||
wxString highHz = wxT("nil");
|
||||
wxString centerHz = wxT("nil");
|
||||
wxString bandwidth = wxT("nil");
|
||||
|
||||
#if defined(EXPERIMENTAL_SPECTRAL_EDITING)
|
||||
if (mF0 >= 0.0) {
|
||||
lowHz.Printf(wxT("(float %g)"), mF0);
|
||||
}
|
||||
|
||||
if (mF1 >= 0.0) {
|
||||
highHz.Printf(wxT("(float %g)"), mF1);
|
||||
}
|
||||
|
||||
if ((mF0 >= 0.0) && (mF1 >= 0.0)) {
|
||||
centerHz.Printf(wxT("(float %g)"), sqrt(mF0 * mF1));
|
||||
}
|
||||
|
||||
if ((mF0 > 0.0) && (mF1 > mF0)) {
|
||||
bandwidth.Printf(wxT("(float %g)"), log(mF1 / mF0)/log(2.0));
|
||||
}
|
||||
|
||||
#endif
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'LOW-HZ)\n"), lowHz.c_str());
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'CENTER-HZ)\n"), centerHz.c_str());
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'HIGH-HZ)\n"), highHz.c_str());
|
||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* %s 'BANDWIDTH)\n"), bandwidth.c_str());
|
||||
|
||||
}
|
||||
|
||||
// Keep track of whether the current track is first selected in its sync-lock group
|
||||
// (we have no idea what the length of the returned audio will be, so we have
|
||||
// to handle sync-lock group behavior the "old" way).
|
||||
@ -779,16 +895,7 @@ bool EffectNyquist::ProcessOne()
|
||||
{
|
||||
nyx_rval rval;
|
||||
|
||||
if (GetEffectFlags() & INSERT_EFFECT) {
|
||||
nyx_set_audio_params(mCurTrack[0]->GetRate(), 0);
|
||||
}
|
||||
else {
|
||||
nyx_set_audio_params(mCurTrack[0]->GetRate(), mCurLen);
|
||||
|
||||
nyx_set_input_audio(StaticGetCallback, (void *)this,
|
||||
mCurNumChannels,
|
||||
mCurLen, mCurTrack[0]->GetRate());
|
||||
}
|
||||
nyx_set_audio_name(mVersion >= 4 ? "*TRACK*" : "S");
|
||||
|
||||
wxString cmd;
|
||||
|
||||
@ -810,6 +917,97 @@ bool EffectNyquist::ProcessOne()
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mVersion >= 4) {
|
||||
cmd += mProps;
|
||||
|
||||
// Set the track TYPE and VIEW properties
|
||||
wxString type;
|
||||
wxString view;
|
||||
wxString bitFormat;
|
||||
switch (mCurTrack[0]->GetKind())
|
||||
{
|
||||
case Track::Wave:
|
||||
type = wxT("wave");
|
||||
switch (((WaveTrack *) mCurTrack[0])->GetDisplay())
|
||||
{
|
||||
case WaveTrack::WaveformDisplay: view = wxT("Waveform"); break;
|
||||
case WaveTrack::WaveformDBDisplay: view = wxT("Waveform (dB)"); break;
|
||||
case WaveTrack::SpectrumDisplay: view = wxT("Spectrogram"); break;
|
||||
case WaveTrack::SpectrumLogDisplay: view = wxT("Spectrogram log(f)"); break;
|
||||
case WaveTrack::PitchDisplay: view = wxT("Pitch (EAC)"); break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
#if defined(USE_MIDI)
|
||||
case Track::Note:
|
||||
type = wxT("midi");
|
||||
view = wxT("Midi");
|
||||
break;
|
||||
#endif
|
||||
case Track::Label:
|
||||
type = wxT("label");
|
||||
view = wxT("Label");
|
||||
break;
|
||||
case Track::Time:
|
||||
type = wxT("time");
|
||||
view = wxT("Time");
|
||||
break;
|
||||
}
|
||||
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* %d 'INDEX)\n"), ++mTrackIndex);
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* \"%s\" 'NAME)\n"), mCurTrack[0]->GetName().c_str());
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* \"%s\" 'TYPE)\n"), type.c_str());
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* \"%s\" 'VIEW)\n"), view.c_str());
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* %d 'CHANNELS)\n"), mCurNumChannels);
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* (float %g) 'START-TIME)\n"), mCurTrack[0]->GetStartTime());
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* (float %g) 'END-TIME)\n"), mCurTrack[0]->GetEndTime());
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* (float %g) 'GAIN)\n"), mCurTrack[0]->GetGain());
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* (float %g) 'PAN)\n"), mCurTrack[0]->GetPan());
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* (float %g) 'RATE)\n"), mCurTrack[0]->GetRate());
|
||||
|
||||
switch (mCurTrack[0]->GetSampleFormat())
|
||||
{
|
||||
case int16Sample:
|
||||
bitFormat = wxT("16");
|
||||
break;
|
||||
case int24Sample:
|
||||
bitFormat = wxT("24");
|
||||
break;
|
||||
case floatSample:
|
||||
bitFormat = wxT("32.0");
|
||||
break;
|
||||
}
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* %s 'FORMAT)\n"), bitFormat.c_str());
|
||||
|
||||
float maxPeak = 0.0;
|
||||
wxString clips;
|
||||
for (int i = 0; i < mCurNumChannels; i++) {
|
||||
WaveClipArray ca;
|
||||
mCurTrack[i]->FillSortedClipArray(ca);
|
||||
for (size_t j = 0; j < ca.GetCount(); j++) {
|
||||
clips += wxString::Format(wxT("(list (float %g) (float %g))"), ca[j]->GetStartTime(), ca[j]->GetEndTime());
|
||||
}
|
||||
|
||||
float min, max;
|
||||
mCurTrack[i]->GetMinMax(&min, &max, mT0, mT1);
|
||||
maxPeak = wxMax(wxMax(fabs(min), fabs(max)), maxPeak);
|
||||
}
|
||||
|
||||
cmd += wxString::Format(wxT("(putprop '*TRACK* (list %s) 'CLIPS)\n"), clips.c_str());
|
||||
cmd += wxString::Format(wxT("(putprop '*SELECTION* (float %g) 'PEAK-LEVEL)\n"), maxPeak);
|
||||
}
|
||||
|
||||
if (GetEffectFlags() & INSERT_EFFECT) {
|
||||
nyx_set_audio_params(mCurTrack[0]->GetRate(), 0);
|
||||
}
|
||||
else {
|
||||
nyx_set_audio_params(mCurTrack[0]->GetRate(), mCurLen);
|
||||
|
||||
nyx_set_input_audio(StaticGetCallback, (void *)this,
|
||||
mCurNumChannels,
|
||||
mCurLen, mCurTrack[0]->GetRate());
|
||||
}
|
||||
|
||||
if (mDebug) {
|
||||
cmd += wxT("(setf *tracenable* T)\n");
|
||||
if (mExternal) {
|
||||
@ -1157,7 +1355,6 @@ void EffectNyquist::OutputCallback(int c)
|
||||
mDebugOutput += (char)c;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << (char)c;
|
||||
}
|
||||
|
||||
@ -1196,6 +1393,22 @@ void EffectNyquist::OSCallback()
|
||||
#endif
|
||||
}
|
||||
|
||||
wxArrayString EffectNyquist::GetNyquistSearchPath()
|
||||
{
|
||||
wxArrayString audacityPathList = wxGetApp().audacityPathList;
|
||||
wxArrayString pathList;
|
||||
|
||||
for (size_t i = 0; i < audacityPathList.GetCount(); i++)
|
||||
{
|
||||
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("nyquist"), pathList);
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("plugins"), pathList);
|
||||
wxGetApp().AddUniquePathToPathList(prefix + wxT("plug-ins"), pathList);
|
||||
}
|
||||
|
||||
return pathList;
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
#define ID_NYQ_SLIDER 2000
|
||||
|
@ -121,6 +121,8 @@ class AUDACITY_DLL_API EffectNyquist:public Effect
|
||||
virtual bool SupportsChains();
|
||||
virtual bool TransferParameters( Shuttle & shuttle );
|
||||
|
||||
static wxArrayString GetNyquistSearchPath();
|
||||
|
||||
private:
|
||||
|
||||
static wxString NyquistToWxString(const char *nyqString);
|
||||
@ -177,12 +179,14 @@ class AUDACITY_DLL_API EffectNyquist:public Effect
|
||||
bool mDebug;
|
||||
std::string mDebugOutput;
|
||||
|
||||
int mVersion;
|
||||
NyqControlArray mControls;
|
||||
|
||||
int mCurNumChannels;
|
||||
WaveTrack *mCurTrack[2];
|
||||
sampleCount mCurStart[2];
|
||||
sampleCount mCurLen;
|
||||
int mTrackIndex;
|
||||
bool mFirstInGroup;
|
||||
double mOutputTime;
|
||||
int mCount;
|
||||
@ -199,6 +203,8 @@ class AUDACITY_DLL_API EffectNyquist:public Effect
|
||||
|
||||
wxArrayString mCategories;
|
||||
|
||||
wxString mProps;
|
||||
|
||||
friend class NyquistDialog;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user