@@ -0,0 +1,215 @@ | |||
/* | |||
* Carla Native Plugin API (JACK Compatibility header) | |||
* Copyright (C) 2015 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
* published by the Free Software Foundation; either version 2 of | |||
* the License, or any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
*/ | |||
#ifndef CARLA_NATIVE_JACK_H_INCLUDED | |||
#define CARLA_NATIVE_JACK_H_INCLUDED | |||
#include "CarlaNative.h" | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Macros */ | |||
#define JACK_DEFAULT_AUDIO_TYPE "audio" | |||
#define JACK_DEFAULT_MIDI_TYPE "midi" | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Basic types */ | |||
typedef float jack_default_audio_sample_t; | |||
typedef uint32_t jack_nframes_t; | |||
typedef void (*jack_shutdown_callback)(void* ptr); | |||
typedef int (*jack_process_callback)(jack_nframes_t nframes, void* ptr); | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Enums */ | |||
typedef enum { | |||
JackPortIsInput = 1 << 0, | |||
JackPortIsOutput = 1 << 1 | |||
} jack___t; | |||
typedef enum { | |||
JackNoStartServer = 0, | |||
JackServerName | |||
} jack_options_t; | |||
typedef enum { | |||
JackNoError = 0x0 | |||
} jack_status_t; | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Structs */ | |||
typedef struct { | |||
bool isInput; | |||
void* buffer; | |||
} jack_port_t; | |||
typedef struct { | |||
// current state | |||
bool active; | |||
const char* clientName; | |||
jack_nframes_t bufferSize; | |||
jack_nframes_t sampleRate; | |||
// callbacks | |||
jack_process_callback processCallback; | |||
void* processPtr; | |||
// ports | |||
jack_port_t* portsAudioIn[8]; | |||
jack_port_t* portsAudioOut[8]; | |||
} jack_client_t; | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Client functions, defined in the plugin code */ | |||
jack_client_t* jack_client_open(const char* clientname, jack_options_t options, jack_status_t* status, ...); | |||
int jack_client_close(jack_client_t* client); | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Callback functions */ | |||
static inline | |||
int jack_on_shutdown(jack_client_t* client, jack_shutdown_callback callback, void* ptr) | |||
{ | |||
return 0; | |||
// unused | |||
(void)client; | |||
(void)callback; | |||
(void)ptr; | |||
} | |||
static inline | |||
int jack_set_process_callback(jack_client_t* client, jack_process_callback callback, void* ptr) | |||
{ | |||
client->processCallback = callback; | |||
client->processPtr = ptr; | |||
return 0; | |||
} | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Port functions */ | |||
static inline | |||
jack_port_t* jack_port_register(jack_client_t* client, const char* name, const char* type, jack___t hints, jack_nframes_t buffersize) | |||
{ | |||
jack_port_t** const ports = (hints & JackPortIsInput) ? client->portsAudioIn : client->portsAudioOut; | |||
for (int i=0; i<8; ++i) | |||
{ | |||
if (ports[i] != NULL) | |||
continue; | |||
jack_port_t* const port = (jack_port_t*)calloc(1, sizeof(jack_port_t)); | |||
if (port == NULL) | |||
return NULL; | |||
port->isInput = (hints & JackPortIsInput); | |||
ports[i] = port; | |||
return port; | |||
} | |||
return NULL; | |||
// unused | |||
(void)name; | |||
(void)type; | |||
(void)buffersize; | |||
} | |||
static inline | |||
int jack_port_unregister(jack_client_t* client, jack_port_t* port) | |||
{ | |||
jack_port_t** const ports = port->isInput ? client->portsAudioIn : client->portsAudioOut; | |||
for (int i=0; i<8; ++i) | |||
{ | |||
if (ports[i] == port) | |||
{ | |||
ports[i] = nullptr; | |||
return 0; | |||
} | |||
} | |||
return 1; | |||
} | |||
static inline | |||
void* jack_port_get_buffer(const jack_port_t* port, jack_nframes_t nframes) | |||
{ | |||
return port->buffer; | |||
// unused | |||
(void)nframes; | |||
} | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* [De/]Activate */ | |||
static inline | |||
int jack_activate(jack_client_t* client) | |||
{ | |||
client->active = true; | |||
return 0; | |||
} | |||
static inline | |||
int jack_deactivate(jack_client_t* client) | |||
{ | |||
client->active = false; | |||
return 0; | |||
} | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
* Get data functions */ | |||
static inline | |||
const char* jack_get_client_name(const jack_client_t* client) | |||
{ | |||
return client->clientName; | |||
} | |||
static inline | |||
jack_nframes_t jack_get_buffer_size(const jack_client_t* client) | |||
{ | |||
return client->bufferSize; | |||
} | |||
static inline | |||
jack_nframes_t jack_get_sample_rate(const jack_client_t* client) | |||
{ | |||
return client->sampleRate; | |||
} | |||
/* ------------------------------------------------------------------------------------------------------------ */ | |||
#ifdef __cplusplus | |||
} /* extern "C" */ | |||
#endif | |||
#endif /* CARLA_NATIVE_JACK_H_INCLUDED */ |
@@ -0,0 +1,369 @@ | |||
/* | |||
* Carla Native Plugins | |||
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
* published by the Free Software Foundation; either version 2 of | |||
* the License, or any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
*/ | |||
#include "CarlaNative.hpp" | |||
#include "CarlaMutex.hpp" | |||
#include "CarlaJuceUtils.hpp" | |||
#include "juce_audio_basics.h" | |||
#include "zita-jaaa/source/audio.cc" | |||
#include "zita-jaaa/source/rngen.cc" | |||
#include "zita-jaaa/source/spectwin.cc" | |||
#include "zita-jaaa/source/styles.cc" | |||
using juce::FloatVectorOperations; | |||
using juce::ScopedPointer; | |||
// ----------------------------------------------------------------------- | |||
// fake jack_client_open/close per plugin | |||
static jack_client_t* gLastJackClient = nullptr; | |||
jack_client_t* jack_client_open(const char*, jack_options_t, jack_status_t* status, ...) | |||
{ | |||
if (status != NULL) | |||
*status = JackNoError; | |||
return gLastJackClient; | |||
} | |||
int jack_client_close(jack_client_t* client) | |||
{ | |||
carla_zeroStruct(client, 1); | |||
return 0; | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Jaaa Plugin | |||
class JaaaPlugin : public NativePluginClass | |||
{ | |||
public: | |||
enum Parameters { | |||
kParameterInput = 0, | |||
kParameterCount | |||
}; | |||
JaaaPlugin(const NativeHostDescriptor* const host) | |||
: NativePluginClass(host), | |||
fJackClient(), | |||
fMutex(), | |||
xrm(), | |||
itcc(nullptr), | |||
driver(nullptr), | |||
display(nullptr), | |||
rootwin(nullptr), | |||
mainwin(nullptr), | |||
xhandler(nullptr), | |||
leakDetector_JaaaPlugin() | |||
{ | |||
CARLA_SAFE_ASSERT(host != nullptr); | |||
int argc = 1; | |||
char* argv[] = { (char*)"jaaa" }; | |||
xrm.init(&argc, argv, (char*)"jaaa", nullptr, 0); | |||
fParameters[kParameterInput] = 1.0f; | |||
} | |||
// ------------------------------------------------------------------- | |||
// Plugin parameter calls | |||
uint32_t getParameterCount() const override | |||
{ | |||
return kParameterCount; | |||
} | |||
const NativeParameter* getParameterInfo(const uint32_t index) const override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(index < kParameterCount, nullptr); | |||
static NativeParameter param; | |||
int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_AUTOMABLE; | |||
// reset | |||
param.name = nullptr; | |||
param.unit = nullptr; | |||
param.ranges.def = 0.0f; | |||
param.ranges.min = 0.0f; | |||
param.ranges.max = 1.0f; | |||
param.ranges.step = 1.0f; | |||
param.ranges.stepSmall = 1.0f; | |||
param.ranges.stepLarge = 1.0f; | |||
param.scalePointCount = 0; | |||
param.scalePoints = nullptr; | |||
switch (index) | |||
{ | |||
case kParameterInput: | |||
hints |= NATIVE_PARAMETER_IS_INTEGER; | |||
param.name = "Input"; | |||
param.ranges.def = 1.0f; | |||
param.ranges.min = 1.0f; | |||
param.ranges.max = 8.0f; | |||
break; | |||
} | |||
param.hints = static_cast<NativeParameterHints>(hints); | |||
return ¶m; | |||
} | |||
float getParameterValue(const uint32_t index) const override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(index < kParameterCount, 0.0f); | |||
return fParameters[index]; | |||
} | |||
// ------------------------------------------------------------------- | |||
// Plugin state calls | |||
void setParameterValue(const uint32_t index, const float value) override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(index < kParameterCount,); | |||
fParameters[index] = value; | |||
} | |||
// ------------------------------------------------------------------- | |||
// Plugin process calls | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override | |||
{ | |||
const CarlaMutexTryLocker cmtl(fMutex); | |||
if (itcc == nullptr || ! fJackClient.active || ! cmtl.wasLocked()) | |||
{ | |||
const int iframes(static_cast<int>(frames)); | |||
for (int i=0; i<8; ++i) | |||
FloatVectorOperations::clear(outBuffer[i], iframes); | |||
return; | |||
} | |||
for (int i=0; i<8; ++i) | |||
fJackClient.portsAudioIn[i]->buffer = inBuffer[i]; | |||
for (int i=0; i<8; ++i) | |||
fJackClient.portsAudioOut[i]->buffer = outBuffer[i]; | |||
fJackClient.processCallback(frames, fJackClient.processPtr); | |||
} | |||
// ------------------------------------------------------------------- | |||
// Plugin UI calls | |||
void uiShow(const bool show) override | |||
{ | |||
const CarlaMutexLocker cml(fMutex); | |||
if (show) | |||
{ | |||
if (itcc == nullptr) | |||
{ | |||
carla_zeroStruct(fJackClient); | |||
gLastJackClient = &fJackClient; | |||
fJackClient.clientName = getUiName(); | |||
fJackClient.bufferSize = getBufferSize(); | |||
fJackClient.sampleRate = getSampleRate(); | |||
itcc = new ITC_ctrl(); | |||
driver = new Audio(itcc, getUiName()); | |||
driver->init_jack(nullptr); | |||
display = new X_display(nullptr); | |||
if (display->dpy() == nullptr) | |||
{ | |||
driver = nullptr; | |||
itcc = nullptr; | |||
return hostUiUnavailable(); | |||
} | |||
init_styles(display, &xrm); | |||
rootwin = new X_rootwin(display); | |||
mainwin = new Spectwin(rootwin, &xrm, driver); | |||
xhandler = new X_handler(display, itcc, EV_X11); | |||
if (const uintptr_t winId = getUiParentId()) | |||
XSetTransientForHint(display->dpy(), mainwin->win(), static_cast<Window>(winId)); | |||
} | |||
xhandler->next_event(); | |||
XFlush(display->dpy()); | |||
} | |||
else | |||
{ | |||
xhandler = nullptr; | |||
mainwin = nullptr; | |||
rootwin = nullptr; | |||
display = nullptr; | |||
driver = nullptr; | |||
itcc = nullptr; | |||
carla_zeroStruct(fJackClient); | |||
} | |||
} | |||
void uiIdle() override | |||
{ | |||
if (itcc == nullptr) | |||
return; | |||
//for (int i=3; --i>=0;) | |||
{ | |||
switch (itcc->get_event()) | |||
{ | |||
case EV_TRIG: | |||
mainwin->handle_trig(); | |||
rootwin->handle_event(); | |||
XFlush(display->dpy()); | |||
break; | |||
case EV_MESG: | |||
mainwin->handle_mesg(itcc->get_message()); | |||
rootwin->handle_event(); | |||
XFlush(display->dpy()); | |||
break; | |||
case EV_X11: | |||
rootwin->handle_event(); | |||
xhandler->next_event(); | |||
break; | |||
} | |||
} | |||
// check if parameters were updated | |||
if (mainwin->_input+1 != static_cast<int>(fParameters[kParameterInput])) | |||
{ | |||
fParameters[kParameterInput] = mainwin->_input+1; | |||
uiParameterChanged(kParameterInput, fParameters[kParameterInput]); | |||
} | |||
// check if UI was closed | |||
if (! mainwin->running()) | |||
{ | |||
{ | |||
const CarlaMutexLocker cml(fMutex); | |||
xhandler = nullptr; | |||
mainwin = nullptr; | |||
rootwin = nullptr; | |||
display = nullptr; | |||
driver = nullptr; | |||
itcc = nullptr; | |||
carla_zeroStruct(fJackClient); | |||
} | |||
uiClosed(); | |||
return; | |||
} | |||
} | |||
void uiSetParameterValue(const uint32_t index, const float value) override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(index < kParameterCount,); | |||
const CarlaMutexLocker cml(fMutex); | |||
if (itcc == nullptr) | |||
return; | |||
switch (index) | |||
{ | |||
case kParameterInput: | |||
mainwin->set_input(static_cast<int>(value)-1); | |||
break; | |||
} | |||
} | |||
// ------------------------------------------------------------------- | |||
// Plugin dispatcher calls | |||
void bufferSizeChanged(const uint32_t bufferSize) override | |||
{ | |||
fJackClient.bufferSize = bufferSize; | |||
} | |||
void sampleRateChanged(const double sampleRate) override | |||
{ | |||
fJackClient.sampleRate = sampleRate; | |||
} | |||
// ------------------------------------------------------------------- | |||
private: | |||
// Fake jack client | |||
jack_client_t fJackClient; | |||
// Mutex just in case | |||
CarlaMutex fMutex; | |||
// Zita stuff (core) | |||
X_resman xrm; | |||
ScopedPointer<ITC_ctrl> itcc; | |||
ScopedPointer<Audio> driver; | |||
ScopedPointer<X_display> display; | |||
ScopedPointer<X_rootwin> rootwin; | |||
ScopedPointer<Spectwin> mainwin; | |||
ScopedPointer<X_handler> xhandler; | |||
float fParameters[kParameterCount]; | |||
PluginClassEND(JaaaPlugin) | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JaaaPlugin) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
static const NativePluginDescriptor jaaaDesc = { | |||
/* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, | |||
/* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
|NATIVE_PLUGIN_HAS_UI | |||
|NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS | |||
|NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
|NATIVE_PLUGIN_USES_PARENT_ID), | |||
/* supports */ static_cast<NativePluginSupports>(0x0), | |||
/* audioIns */ 8, | |||
/* audioOuts */ 8, | |||
/* midiIns */ 0, | |||
/* midiOuts */ 0, | |||
/* paramIns */ JaaaPlugin::kParameterCount, | |||
/* paramOuts */ 0, | |||
/* name */ "Jaaa", | |||
/* label */ "jaaa", | |||
/* maker */ "Fons Adriaensen", | |||
/* copyright */ "GPL v2+", | |||
PluginDescriptorFILL(JaaaPlugin) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
CARLA_EXPORT | |||
void carla_register_native_plugin_zita_jaaa(); | |||
CARLA_EXPORT | |||
void carla_register_native_plugin_zita_jaaa() | |||
{ | |||
carla_register_native_plugin(&jaaaDesc); | |||
} | |||
// ----------------------------------------------------------------------- |
@@ -0,0 +1 @@ | |||
Fons Adriaensen <fons@linuxaudio.org> |
@@ -0,0 +1,340 @@ | |||
GNU GENERAL PUBLIC LICENSE | |||
Version 2, June 1991 | |||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
Everyone is permitted to copy and distribute verbatim copies | |||
of this license document, but changing it is not allowed. | |||
Preamble | |||
The licenses for most software are designed to take away your | |||
freedom to share and change it. By contrast, the GNU General Public | |||
License is intended to guarantee your freedom to share and change free | |||
software--to make sure the software is free for all its users. This | |||
General Public License applies to most of the Free Software | |||
Foundation's software and to any other program whose authors commit to | |||
using it. (Some other Free Software Foundation software is covered by | |||
the GNU Library General Public License instead.) You can apply it to | |||
your programs, too. | |||
When we speak of free software, we are referring to freedom, not | |||
price. Our General Public Licenses are designed to make sure that you | |||
have the freedom to distribute copies of free software (and charge for | |||
this service if you wish), that you receive source code or can get it | |||
if you want it, that you can change the software or use pieces of it | |||
in new free programs; and that you know you can do these things. | |||
To protect your rights, we need to make restrictions that forbid | |||
anyone to deny you these rights or to ask you to surrender the rights. | |||
These restrictions translate to certain responsibilities for you if you | |||
distribute copies of the software, or if you modify it. | |||
For example, if you distribute copies of such a program, whether | |||
gratis or for a fee, you must give the recipients all the rights that | |||
you have. You must make sure that they, too, receive or can get the | |||
source code. And you must show them these terms so they know their | |||
rights. | |||
We protect your rights with two steps: (1) copyright the software, and | |||
(2) offer you this license which gives you legal permission to copy, | |||
distribute and/or modify the software. | |||
Also, for each author's protection and ours, we want to make certain | |||
that everyone understands that there is no warranty for this free | |||
software. If the software is modified by someone else and passed on, we | |||
want its recipients to know that what they have is not the original, so | |||
that any problems introduced by others will not reflect on the original | |||
authors' reputations. | |||
Finally, any free program is threatened constantly by software | |||
patents. We wish to avoid the danger that redistributors of a free | |||
program will individually obtain patent licenses, in effect making the | |||
program proprietary. To prevent this, we have made it clear that any | |||
patent must be licensed for everyone's free use or not licensed at all. | |||
The precise terms and conditions for copying, distribution and | |||
modification follow. | |||
GNU GENERAL PUBLIC LICENSE | |||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |||
0. This License applies to any program or other work which contains | |||
a notice placed by the copyright holder saying it may be distributed | |||
under the terms of this General Public License. The "Program", below, | |||
refers to any such program or work, and a "work based on the Program" | |||
means either the Program or any derivative work under copyright law: | |||
that is to say, a work containing the Program or a portion of it, | |||
either verbatim or with modifications and/or translated into another | |||
language. (Hereinafter, translation is included without limitation in | |||
the term "modification".) Each licensee is addressed as "you". | |||
Activities other than copying, distribution and modification are not | |||
covered by this License; they are outside its scope. The act of | |||
running the Program is not restricted, and the output from the Program | |||
is covered only if its contents constitute a work based on the | |||
Program (independent of having been made by running the Program). | |||
Whether that is true depends on what the Program does. | |||
1. You may copy and distribute verbatim copies of the Program's | |||
source code as you receive it, in any medium, provided that you | |||
conspicuously and appropriately publish on each copy an appropriate | |||
copyright notice and disclaimer of warranty; keep intact all the | |||
notices that refer to this License and to the absence of any warranty; | |||
and give any other recipients of the Program a copy of this License | |||
along with the Program. | |||
You may charge a fee for the physical act of transferring a copy, and | |||
you may at your option offer warranty protection in exchange for a fee. | |||
2. You may modify your copy or copies of the Program or any portion | |||
of it, thus forming a work based on the Program, and copy and | |||
distribute such modifications or work under the terms of Section 1 | |||
above, provided that you also meet all of these conditions: | |||
a) You must cause the modified files to carry prominent notices | |||
stating that you changed the files and the date of any change. | |||
b) You must cause any work that you distribute or publish, that in | |||
whole or in part contains or is derived from the Program or any | |||
part thereof, to be licensed as a whole at no charge to all third | |||
parties under the terms of this License. | |||
c) If the modified program normally reads commands interactively | |||
when run, you must cause it, when started running for such | |||
interactive use in the most ordinary way, to print or display an | |||
announcement including an appropriate copyright notice and a | |||
notice that there is no warranty (or else, saying that you provide | |||
a warranty) and that users may redistribute the program under | |||
these conditions, and telling the user how to view a copy of this | |||
License. (Exception: if the Program itself is interactive but | |||
does not normally print such an announcement, your work based on | |||
the Program is not required to print an announcement.) | |||
These requirements apply to the modified work as a whole. If | |||
identifiable sections of that work are not derived from the Program, | |||
and can be reasonably considered independent and separate works in | |||
themselves, then this License, and its terms, do not apply to those | |||
sections when you distribute them as separate works. But when you | |||
distribute the same sections as part of a whole which is a work based | |||
on the Program, the distribution of the whole must be on the terms of | |||
this License, whose permissions for other licensees extend to the | |||
entire whole, and thus to each and every part regardless of who wrote it. | |||
Thus, it is not the intent of this section to claim rights or contest | |||
your rights to work written entirely by you; rather, the intent is to | |||
exercise the right to control the distribution of derivative or | |||
collective works based on the Program. | |||
In addition, mere aggregation of another work not based on the Program | |||
with the Program (or with a work based on the Program) on a volume of | |||
a storage or distribution medium does not bring the other work under | |||
the scope of this License. | |||
3. You may copy and distribute the Program (or a work based on it, | |||
under Section 2) in object code or executable form under the terms of | |||
Sections 1 and 2 above provided that you also do one of the following: | |||
a) Accompany it with the complete corresponding machine-readable | |||
source code, which must be distributed under the terms of Sections | |||
1 and 2 above on a medium customarily used for software interchange; or, | |||
b) Accompany it with a written offer, valid for at least three | |||
years, to give any third party, for a charge no more than your | |||
cost of physically performing source distribution, a complete | |||
machine-readable copy of the corresponding source code, to be | |||
distributed under the terms of Sections 1 and 2 above on a medium | |||
customarily used for software interchange; or, | |||
c) Accompany it with the information you received as to the offer | |||
to distribute corresponding source code. (This alternative is | |||
allowed only for noncommercial distribution and only if you | |||
received the program in object code or executable form with such | |||
an offer, in accord with Subsection b above.) | |||
The source code for a work means the preferred form of the work for | |||
making modifications to it. For an executable work, complete source | |||
code means all the source code for all modules it contains, plus any | |||
associated interface definition files, plus the scripts used to | |||
control compilation and installation of the executable. However, as a | |||
special exception, the source code distributed need not include | |||
anything that is normally distributed (in either source or binary | |||
form) with the major components (compiler, kernel, and so on) of the | |||
operating system on which the executable runs, unless that component | |||
itself accompanies the executable. | |||
If distribution of executable or object code is made by offering | |||
access to copy from a designated place, then offering equivalent | |||
access to copy the source code from the same place counts as | |||
distribution of the source code, even though third parties are not | |||
compelled to copy the source along with the object code. | |||
4. You may not copy, modify, sublicense, or distribute the Program | |||
except as expressly provided under this License. Any attempt | |||
otherwise to copy, modify, sublicense or distribute the Program is | |||
void, and will automatically terminate your rights under this License. | |||
However, parties who have received copies, or rights, from you under | |||
this License will not have their licenses terminated so long as such | |||
parties remain in full compliance. | |||
5. You are not required to accept this License, since you have not | |||
signed it. However, nothing else grants you permission to modify or | |||
distribute the Program or its derivative works. These actions are | |||
prohibited by law if you do not accept this License. Therefore, by | |||
modifying or distributing the Program (or any work based on the | |||
Program), you indicate your acceptance of this License to do so, and | |||
all its terms and conditions for copying, distributing or modifying | |||
the Program or works based on it. | |||
6. Each time you redistribute the Program (or any work based on the | |||
Program), the recipient automatically receives a license from the | |||
original licensor to copy, distribute or modify the Program subject to | |||
these terms and conditions. You may not impose any further | |||
restrictions on the recipients' exercise of the rights granted herein. | |||
You are not responsible for enforcing compliance by third parties to | |||
this License. | |||
7. If, as a consequence of a court judgment or allegation of patent | |||
infringement or for any other reason (not limited to patent issues), | |||
conditions are imposed on you (whether by court order, agreement or | |||
otherwise) that contradict the conditions of this License, they do not | |||
excuse you from the conditions of this License. If you cannot | |||
distribute so as to satisfy simultaneously your obligations under this | |||
License and any other pertinent obligations, then as a consequence you | |||
may not distribute the Program at all. For example, if a patent | |||
license would not permit royalty-free redistribution of the Program by | |||
all those who receive copies directly or indirectly through you, then | |||
the only way you could satisfy both it and this License would be to | |||
refrain entirely from distribution of the Program. | |||
If any portion of this section is held invalid or unenforceable under | |||
any particular circumstance, the balance of the section is intended to | |||
apply and the section as a whole is intended to apply in other | |||
circumstances. | |||
It is not the purpose of this section to induce you to infringe any | |||
patents or other property right claims or to contest validity of any | |||
such claims; this section has the sole purpose of protecting the | |||
integrity of the free software distribution system, which is | |||
implemented by public license practices. Many people have made | |||
generous contributions to the wide range of software distributed | |||
through that system in reliance on consistent application of that | |||
system; it is up to the author/donor to decide if he or she is willing | |||
to distribute software through any other system and a licensee cannot | |||
impose that choice. | |||
This section is intended to make thoroughly clear what is believed to | |||
be a consequence of the rest of this License. | |||
8. If the distribution and/or use of the Program is restricted in | |||
certain countries either by patents or by copyrighted interfaces, the | |||
original copyright holder who places the Program under this License | |||
may add an explicit geographical distribution limitation excluding | |||
those countries, so that distribution is permitted only in or among | |||
countries not thus excluded. In such case, this License incorporates | |||
the limitation as if written in the body of this License. | |||
9. The Free Software Foundation may publish revised and/or new versions | |||
of the General Public License from time to time. Such new versions will | |||
be similar in spirit to the present version, but may differ in detail to | |||
address new problems or concerns. | |||
Each version is given a distinguishing version number. If the Program | |||
specifies a version number of this License which applies to it and "any | |||
later version", you have the option of following the terms and conditions | |||
either of that version or of any later version published by the Free | |||
Software Foundation. If the Program does not specify a version number of | |||
this License, you may choose any version ever published by the Free Software | |||
Foundation. | |||
10. If you wish to incorporate parts of the Program into other free | |||
programs whose distribution conditions are different, write to the author | |||
to ask for permission. For software which is copyrighted by the Free | |||
Software Foundation, write to the Free Software Foundation; we sometimes | |||
make exceptions for this. Our decision will be guided by the two goals | |||
of preserving the free status of all derivatives of our free software and | |||
of promoting the sharing and reuse of software generally. | |||
NO WARRANTY | |||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |||
REPAIR OR CORRECTION. | |||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |||
POSSIBILITY OF SUCH DAMAGES. | |||
END OF TERMS AND CONDITIONS | |||
How to Apply These Terms to Your New Programs | |||
If you develop a new program, and you want it to be of the greatest | |||
possible use to the public, the best way to achieve this is to make it | |||
free software which everyone can redistribute and change under these terms. | |||
To do so, attach the following notices to the program. It is safest | |||
to attach them to the start of each source file to most effectively | |||
convey the exclusion of warranty; and each file should have at least | |||
the "copyright" line and a pointer to where the full notice is found. | |||
<one line to give the program's name and a brief idea of what it does.> | |||
Copyright (C) <year> <name of author> | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
Also add information on how to contact you by electronic and paper mail. | |||
If the program is interactive, make it output a short notice like this | |||
when it starts in an interactive mode: | |||
Gnomovision version 69, Copyright (C) year name of author | |||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||
This is free software, and you are welcome to redistribute it | |||
under certain conditions; type `show c' for details. | |||
The hypothetical commands `show w' and `show c' should show the appropriate | |||
parts of the General Public License. Of course, the commands you use may | |||
be called something other than `show w' and `show c'; they could even be | |||
mouse-clicks or menu items--whatever suits your program. | |||
You should also get your employer (if you work as a programmer) or your | |||
school, if any, to sign a "copyright disclaimer" for the program, if | |||
necessary. Here is a sample; alter the names: | |||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |||
`Gnomovision' (which makes passes at compilers) written by James Hacker. | |||
<signature of Ty Coon>, 1 April 1989 | |||
Ty Coon, President of Vice | |||
This General Public License does not permit incorporating your program into | |||
proprietary programs. If your program is a subroutine library, you may | |||
consider it more useful to permit linking proprietary applications with the | |||
library. If this is what you want to do, use the GNU Library General | |||
Public License instead of this License. |
@@ -0,0 +1,16 @@ | |||
To install, cd to this directory, make, sudo make install | |||
You need the shared libraries: | |||
libzita-alsa-pcmi.0.2.0 | |||
libclthreads.so.2.4.0 | |||
libclxclient.so.3.9.0 | |||
and the corresponding header files installed. These are available at | |||
<http://kokkinizita.linuxaudio.org/linuxaudio/downloads/index.html> | |||
You also need libfftw3f, which comes with most Linux distributions. | |||
-- | |||
FA | |||
@@ -0,0 +1,101 @@ | |||
JAAA -- Quick manual | |||
____________________ | |||
Some buttons will light up yellow when you click on them, | |||
and there will be at most one of those active at any time. | |||
This indicates the 'current parameter', which in most | |||
cases can be modified in a number of ways: | |||
- by typing a new value into the text widget, followed by ENTER, | |||
- by using the '<' or '>' buttons to decrement or increment, | |||
- by using the mouse wheel, | |||
- by mouse gestures inside the display area. | |||
Input | |||
----- | |||
Select on of the four inputs. | |||
Frequency and Amplitude | |||
----------------------- | |||
Frequency: | |||
'Min' and 'Max' set the min and max displayed frequencies. | |||
If either of these is selected then | |||
a horizontal Drag Left changes 'Min', | |||
a horizontal Drag Right changes 'Max'. | |||
'Cent' is the frequency at the middle of the x-axis. | |||
'Span' is 'Max' - 'Min', changing this value preserves 'Cent'. | |||
If either of these is selected then | |||
a horizontal Drag Left changes 'Cent', | |||
a horizontal Drag Right changes 'Span'. | |||
'Cent' can also be set by Clicking in the frequency axis scale. | |||
Amplitude: | |||
'Max' is the maximum value on the y-axis. | |||
'Range' is the range of the y-axis. | |||
If either of these is selected then | |||
a vertical Drag Left changes 'Max', | |||
a vertical Drag Right changes 'Range', | |||
So for the last four mouse gestures, a Drag Left will scroll the | |||
display, while a Drag Right will zoom in or out. Maybe I will add | |||
and automatic selection of the axis based on the direction of the | |||
mouse gesture. | |||
Analyser | |||
-------- | |||
The analyser is based on a windowed FFT. Actually the windowing is performed | |||
by convolution after the FFT, and combined with interpolation. The windowing | |||
and interpolation ensure that displayed peaks will be accurate to 0.25 dB even | |||
if the peak falls between the FFT bins. More accurate measurements can be made | |||
using the markers (see below). | |||
'Bandw' sets the FFT length, and hence the bandwidth of the analyser. Depending | |||
on this value, the size of the display and the frequency range, you may sometimes | |||
see two traces. This happens when the resolution of the analyser is better than the | |||
display, so that one pixel contains more than one analyser value. In that case, the | |||
dark blue trace is the peak value over the frequency range represented by each pixel, | |||
and lighter one is the average value. The first one is correct for discrete frequencies, | |||
and the latter should be used to read noise densities. | |||
There is no mouse gesture to change the bandwidth. | |||
'VidAv' or video average, when switched on, averages the measured energy over time. | |||
This is mainly used to measure noise. The averaging lenght increases over time, to | |||
a maxumum of 1000 iterations. Changing the input or bandwidth resets and restarts | |||
the averaging. | |||
'Freeze' freezes the analyser, but not the display, so you can still scroll and | |||
zoom or use the markers discussed below. | |||
Markers | |||
------- | |||
Markers are used in order to accurately read off values in the display. There can be | |||
up to two markers, set by clicking at the desired frequency inside the display. | |||
When there are two markers, the second one will move with each click, while the first | |||
remains fixed. Measured values for the two markers, and their difference in frequency | |||
and level are displayed in the upper left corner of the display. | |||
'Clear' clears the markers. | |||
When 'Peak' is selected, clicking inside the display will set a marker at the nearest | |||
peak. The exact frequency and level of the peak are found by interpolation, so the | |||
frequency can be much more accurate than the FFT step, and the level corresponds to | |||
the true peak value regardless of display or analyser resolution. | |||
When 'Noise' is selected, clicking inside the display will set a noise marker. | |||
The noise density (energy per Hz) is calculated and displayed. | |||
@@ -0,0 +1,49 @@ | |||
# -------------------------------------------------------------------------- | |||
# | |||
# Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
# | |||
# This program is free software; you can redistribute it and/or modify | |||
# it under the terms of the GNU General Public License as published by | |||
# the Free Software Foundation; either version 2 of the License, or | |||
# (at your option) any later version. | |||
# | |||
# This program is distributed in the hope that it will be useful, | |||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
# GNU General Public License for more details. | |||
# | |||
# You should have received a copy of the GNU General Public License | |||
# along with this program; if not, write to the Free Software | |||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
# | |||
# -------------------------------------------------------------------------- | |||
PREFIX = /usr/local | |||
SUFFIX := $(shell uname -m | sed -e 's/^unknown/$//' -e 's/^i.86/$//' -e 's/^x86_64/$/64/') | |||
LIBDIR = lib$(SUFFIX) | |||
VERSION = 0.8.4 | |||
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DPREFIX=\"$(PREFIX)\" -I/usr/include/freetype2 | |||
CXXFLAGS += -O2 -Wall -MMD -MP | |||
CXXFLAGS += -march=native | |||
LDFLAGS += -L/usr/X11R6/$(LIBDIR) | |||
LDLIBS += -lzita-alsa-pcmi -lclthreads -lclxclient -lpthread -lfftw3f -ljack -lasound -lpthread -lXft -lX11 -lrt | |||
JAAA_O = jaaa.o styles.o spectwin.o audio.o rngen.o | |||
jaaa: $(JAAA_O) | |||
g++ $(LDFLAGS) -o $@ $(JAAA_O) $(LDLIBS) | |||
$(JAAA_O): | |||
-include $(JAAA_O:%.o=%.d) | |||
install: jaaa | |||
install -Dm 755 jaaa $(DESTDIR)$(PREFIX)/bin/jaaa | |||
uninstall: | |||
rm -f $(DESTDIR)$(PREFIX)/bin/jaaa | |||
clean: | |||
/bin/rm -f *~ *.o *.a *.d *.so jaaa | |||
@@ -0,0 +1,261 @@ | |||
// ------------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ------------------------------------------------------------------------- | |||
#include <math.h> | |||
#include "audio.h" | |||
#include "messages.h" | |||
Audio::Audio (ITC_ctrl *cmain, const char *name) : | |||
A_thread ("Audio"), | |||
_name (name), | |||
_cmain (cmain), | |||
_run_jack (0), | |||
_ncapt (8), | |||
_nplay (8), | |||
_input (-1), | |||
_data (0), | |||
_outs (0) | |||
{ | |||
} | |||
Audio::~Audio (void) | |||
{ | |||
if (_run_jack) close_jack (); | |||
delete[] _outs; | |||
} | |||
void Audio::init (void) | |||
{ | |||
int i; | |||
for (i = 0; i < LSINE; i++) | |||
{ | |||
_sine [i] = sin (2 * M_PI * i / LSINE); | |||
} | |||
_sine [LSINE] = 0; | |||
_g_bits = 0; | |||
_a_noise = 0.0; | |||
_a_sine = 0.0; | |||
_f_sine = 0.0; | |||
_p_sine = 0.0; | |||
} | |||
void Audio::thr_main (void) | |||
{ | |||
put_event (EV_EXIT); | |||
} | |||
void Audio::init_jack (const char *server) | |||
{ | |||
char s [16]; | |||
int opts; | |||
jack_status_t stat; | |||
opts = JackNoStartServer; | |||
if (server) opts |= JackServerName; | |||
if ((_jack_handle = jack_client_open (_name, (jack_options_t) opts, &stat, server)) == 0) | |||
{ | |||
fprintf (stderr, "Can't connect to JACK\n"); | |||
exit (1); | |||
} | |||
jack_set_process_callback (_jack_handle, jack_static_callback, (void *)this); | |||
jack_on_shutdown (_jack_handle, jack_static_shutdown, (void *)this); | |||
for (int i = 0; i < _nplay; i++) | |||
{ | |||
sprintf(s, "out_%d", i + 1); | |||
_jack_out [i] = jack_port_register (_jack_handle, s, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
} | |||
for (int i = 0; i < _ncapt; i++) | |||
{ | |||
sprintf(s, "in_%d", i + 1); | |||
_jack_in [i] = jack_port_register (_jack_handle, s, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
} | |||
_outs = new float [4096]; | |||
init (); | |||
if (jack_activate (_jack_handle)) | |||
{ | |||
fprintf(stderr, "Can't activate JACK"); | |||
exit (1); | |||
} | |||
_fsamp = jack_get_sample_rate (_jack_handle); | |||
_fsize = jack_get_buffer_size (_jack_handle); | |||
_name = jack_get_client_name (_jack_handle); | |||
_run_jack = true; | |||
_cmain->put_event (EV_MESG, new M_jinfo (_fsamp, _fsize, _name)); | |||
} | |||
void Audio::close_jack () | |||
{ | |||
jack_deactivate (_jack_handle); | |||
for (int i = 0; i < _nplay; i++) jack_port_unregister(_jack_handle, _jack_out[i]); | |||
for (int i = 0; i < _ncapt; i++) jack_port_unregister(_jack_handle, _jack_in[i]); | |||
jack_client_close (_jack_handle); | |||
} | |||
void Audio::jack_static_shutdown (void *arg) | |||
{ | |||
return ((Audio *) arg)->jack_shutdown (); | |||
} | |||
void Audio::jack_shutdown (void) | |||
{ | |||
_cmain->put_event (EV_JACK); | |||
} | |||
int Audio::jack_static_callback (jack_nframes_t nframes, void *arg) | |||
{ | |||
return ((Audio *) arg)->jack_callback (nframes); | |||
} | |||
int Audio::jack_callback (jack_nframes_t nframes) | |||
{ | |||
unsigned long b, m, n; | |||
int i; | |||
float *p; | |||
if (_data && _input >= 0) | |||
{ | |||
p = (float *)(jack_port_get_buffer (_jack_in [_input], nframes)); | |||
m = nframes; | |||
n = _size - _dind; | |||
if (m >= n) | |||
{ | |||
memcpy (_data + _dind, p, sizeof(jack_default_audio_sample_t) * n); | |||
_dind = 0; | |||
p += n; | |||
m -= n; | |||
} | |||
if (m) | |||
{ | |||
memcpy (_data + _dind, p, sizeof(jack_default_audio_sample_t) * m); | |||
_dind += m; | |||
} | |||
_scnt += nframes; | |||
} | |||
generate (nframes); | |||
b = _g_bits & 255; | |||
for (i = 0; i < _nplay; i++, b >>= 1) | |||
{ | |||
p = (float *)(jack_port_get_buffer (_jack_out [i], nframes)); | |||
if (b & 1) memcpy (p, _outs, sizeof(jack_default_audio_sample_t) * nframes); | |||
else memset (p, 0, sizeof(jack_default_audio_sample_t) * nframes); | |||
} | |||
process (); | |||
return 0; | |||
} | |||
void Audio::process (void) | |||
{ | |||
int k; | |||
ITC_mesg *M; | |||
if (_data) | |||
{ | |||
k = _scnt / _step; | |||
if (k && _cmain->put_event_try (EV_TRIG, k) == ITC_ctrl::NO_ERROR) _scnt -= k * _step; | |||
} | |||
if (get_event_nowait (1 << EV_MESG) == EV_MESG) | |||
{ | |||
M = get_message (); | |||
if (M->type () == M_BUFFP) | |||
{ | |||
M_buffp *Z = (M_buffp *) M; | |||
_data = Z->_data; | |||
_size = Z->_size; | |||
_step = Z->_step; | |||
_dind = 0; | |||
_scnt = 0; | |||
} | |||
else if (M->type () == M_INPUT) | |||
{ | |||
M_input *Z = (M_input *) M; | |||
_input = Z->_input; | |||
if (_input >= _ncapt) _input = -1; | |||
} | |||
else if (M->type () == M_GENPAR) | |||
{ | |||
M_genpar *Z = (M_genpar *) M; | |||
_g_bits = Z->_g_bits; | |||
_a_noise = sqrt (0.5) * pow (10.0, 0.05 * Z->_a_noise); | |||
_a_sine = pow (10.0, 0.05 * Z->_a_sine); | |||
_f_sine = LSINE * Z->_f_sine / _fsamp; | |||
} | |||
M->recover (); | |||
} | |||
} | |||
void Audio::generate (int size) | |||
{ | |||
int i, j; | |||
float a, p, r; | |||
if (size > 4096) size = 4096; | |||
memset (_outs, 0, size * sizeof (float)); | |||
if (_g_bits & M_genpar::WNOISE) | |||
{ | |||
for (i = 0; i < size; i++) | |||
{ | |||
_outs [i] += _a_noise * _rngen.grandf (); | |||
} | |||
} | |||
if (_g_bits & M_genpar::SINE) | |||
{ | |||
p = _p_sine; | |||
for (i = 0; i < size; i++) | |||
{ | |||
j = (int) p; | |||
if (j == LSINE) a = 0; | |||
else | |||
{ | |||
r = p - j; | |||
a = (1.0 - r) * _sine [j] + r * _sine [j + 1]; | |||
} | |||
_outs [i] += _a_sine * a; | |||
p += _f_sine; | |||
if (p >= LSINE) p -= LSINE; | |||
} | |||
_p_sine = p; | |||
} | |||
} |
@@ -0,0 +1,81 @@ | |||
// ------------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ------------------------------------------------------------------------- | |||
#include <stdlib.h> | |||
#include <math.h> | |||
#include <clthreads.h> | |||
#include "CarlaNativeJack.h" | |||
#include "rngen.h" | |||
class Audio : public A_thread | |||
{ | |||
public: | |||
Audio (ITC_ctrl *cmain, const char *name); | |||
virtual ~Audio (void); | |||
void init_jack (const char *server); | |||
private: | |||
enum { LSINE = 4096, LRAND = 4096, MRAND = LRAND - 1 }; | |||
virtual void thr_main (void); | |||
void init (void); | |||
void process (void); | |||
void generate (int size); | |||
void close_jack (void); | |||
void jack_shutdown (void); | |||
int jack_callback (jack_nframes_t nframes); | |||
const char *_name; | |||
ITC_ctrl *_cmain; | |||
volatile bool _run_jack; | |||
jack_client_t *_jack_handle; | |||
jack_port_t *_jack_in [8]; | |||
jack_port_t *_jack_out [8]; | |||
unsigned long _fsamp; | |||
unsigned long _fsize; | |||
int _ncapt; | |||
int _nplay; | |||
int _input; | |||
float *_data; | |||
int _dind; | |||
int _size; | |||
int _step; | |||
int _scnt; | |||
float _sine [LSINE + 1]; | |||
float *_outs; | |||
int _g_bits; | |||
float _a_noise; | |||
float _a_sine; | |||
float _f_sine; | |||
float _p_sine; | |||
Rngen _rngen; | |||
static void jack_static_shutdown (void *arg); | |||
static int jack_static_callback (jack_nframes_t nframes, void *arg); | |||
}; | |||
@@ -0,0 +1,175 @@ | |||
// ------------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ------------------------------------------------------------------------- | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <clthreads.h> | |||
#include <clxclient.h> | |||
#include <sys/mman.h> | |||
#include "messages.h" | |||
#include "spectwin.h" | |||
#include "audio.h" | |||
#define NOPTS 10 | |||
#define CP (char *) | |||
XrmOptionDescRec options [NOPTS] = | |||
{ | |||
{CP"-h", CP".help", XrmoptionNoArg, CP"true" }, | |||
{CP"-J", CP".jack", XrmoptionNoArg, CP"true" }, | |||
{CP"-s", CP".server", XrmoptionSepArg, 0 }, | |||
{CP"-A", CP".alsa", XrmoptionNoArg, CP"true" }, | |||
{CP"-d", CP".device", XrmoptionSepArg, 0 }, | |||
{CP"-C", CP".capture", XrmoptionSepArg, 0 }, | |||
{CP"-P", CP".playback", XrmoptionSepArg, 0 }, | |||
{CP"-r", CP".fsamp", XrmoptionSepArg, 0 }, | |||
{CP"-p", CP".period", XrmoptionSepArg, 0 }, | |||
{CP"-n", CP".nfrags", XrmoptionSepArg, 0 } | |||
}; | |||
static void help (void) | |||
{ | |||
fprintf (stderr, "\nJaaa-%s\n\n", VERSION); | |||
fprintf (stderr, " (C) 2004-2010 Fons Adriaensen <fons@kokkinizita.net>\n\n"); | |||
fprintf (stderr, "Options:\n"); | |||
fprintf (stderr, " -h Display this text\n"); | |||
fprintf (stderr, " -name <name> Jack and X11 name\n"); | |||
fprintf (stderr, " -J Use JACK, with options:\n"); | |||
fprintf (stderr, " -s <server> Select Jack server\n"); | |||
fprintf (stderr, " -A Use ALSA, with options:\n"); | |||
fprintf (stderr, " -d <device> Alsa device [hw:0]\n"); | |||
fprintf (stderr, " -C <device> Capture device\n"); | |||
fprintf (stderr, " -P <device> Playback device\n"); | |||
fprintf (stderr, " -r <rate> Sample frequency [48000]\n"); | |||
fprintf (stderr, " -p <period> Period size [1024]\n"); | |||
fprintf (stderr, " -n <nfrags> Number of fragments [2]\n\n"); | |||
fprintf (stderr, " Either -J or -A is required.\n\n"); | |||
exit (1); | |||
} | |||
int main (int argc, char *argv []) | |||
{ | |||
X_resman xrm; | |||
X_display *display; | |||
X_handler *xhandler; | |||
X_rootwin *rootwin; | |||
Spectwin *mainwin; | |||
Audio *driver; | |||
ITC_ctrl itcc; | |||
// Initialse resource database | |||
xrm.init (&argc, argv, CP"jaaa", options, NOPTS); | |||
if (xrm.getb (".help", 0)) help (); | |||
// Open display | |||
display = new X_display (xrm.get (".display", 0)); | |||
if (display->dpy () == 0) | |||
{ | |||
fprintf (stderr, "Can't open display !\n"); | |||
delete display; | |||
exit (1); | |||
} | |||
// Open audio interface | |||
driver = new Audio (&itcc, xrm.rname ()); | |||
if (xrm.getb (".jack", 0)) | |||
{ | |||
driver->init_jack (xrm.get (".server", 0)); | |||
} | |||
else if (xrm.getb (".alsa", 0)) | |||
{ | |||
const char *p, *adev, *capt, *play; | |||
int fsamp, period, nfrags; | |||
p = xrm.get (".fsamp", 0); | |||
if (! p || sscanf (p, "%d", &fsamp) != 1) fsamp = 48000; | |||
p = xrm.get (".period", 0); | |||
if (! p || sscanf (p, "%d", &period) != 1) period = 1024; | |||
p = xrm.get (".nfrags", 0); | |||
if (! p || sscanf (p, "%d", &nfrags) != 1) nfrags = 2; | |||
adev = xrm.get (".device", "hw:0"); | |||
capt = xrm.get (".capture", 0); | |||
play = xrm.get (".playback", 0); | |||
if (!capt && !play) capt = play = adev; | |||
driver->init_alsa (play, capt, fsamp, period, nfrags, 4, 4); | |||
} | |||
else help (); | |||
// Initialise resources and create windows | |||
init_styles (display, &xrm); | |||
rootwin = new X_rootwin (display); | |||
mainwin = new Spectwin (rootwin, &xrm, driver); | |||
// Create X handler | |||
xhandler = new X_handler (display, &itcc, EV_X11); | |||
xhandler->next_event (); | |||
XFlush (display->dpy ()); | |||
// Try to lock memory | |||
if (mlockall (MCL_CURRENT | MCL_FUTURE)) | |||
{ | |||
fprintf (stderr, "Warning: memory lock failed.\n"); | |||
} | |||
// Enter main loop | |||
while (mainwin->running ()) | |||
{ | |||
switch (itcc.get_event ()) | |||
{ | |||
case EV_TRIG: | |||
mainwin->handle_trig (); | |||
rootwin->handle_event (); | |||
XFlush (display->dpy ()); | |||
break; | |||
case EV_JACK: | |||
mainwin->handle_term (); | |||
break; | |||
case EV_MESG: | |||
mainwin->handle_mesg (itcc.get_message ()); | |||
rootwin->handle_event (); | |||
XFlush (display->dpy ()); | |||
break; | |||
case EV_X11: | |||
rootwin->handle_event (); | |||
xhandler->next_event (); | |||
break; | |||
} | |||
} | |||
// Cleanup | |||
delete xhandler; | |||
delete driver; | |||
delete mainwin; | |||
delete rootwin; | |||
delete display; | |||
return 0; | |||
} | |||
@@ -0,0 +1,98 @@ | |||
// ------------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ------------------------------------------------------------------------- | |||
#ifndef __MESSAGES_H | |||
#define __MESSAGES_H | |||
#include <clthreads.h> | |||
#define EV_MESG 0 | |||
#define EV_X11 16 | |||
#define EV_JACK 29 | |||
#define EV_TRIG 30 | |||
#define EV_EXIT 31 | |||
#define M_BUFFP 1 | |||
#define M_INPUT 2 | |||
#define M_JINFO 3 | |||
#define M_GENPAR 4 | |||
class M_buffp : public ITC_mesg | |||
{ | |||
public: | |||
M_buffp (float *data, int size, int step) : | |||
ITC_mesg (M_BUFFP), | |||
_data (data), | |||
_size (size), | |||
_step (step) {} | |||
float *_data; | |||
int _size; | |||
int _step; | |||
}; | |||
class M_input : public ITC_mesg | |||
{ | |||
public: | |||
M_input (int input) : | |||
ITC_mesg (M_INPUT), | |||
_input (input) {} | |||
int _input; | |||
}; | |||
class M_jinfo : public ITC_mesg | |||
{ | |||
public: | |||
M_jinfo (unsigned long fsamp, unsigned long fsize, const char *jname) : | |||
ITC_mesg (M_JINFO), | |||
_fsamp (fsamp), | |||
_fsize (fsize), | |||
_jname (jname) {} | |||
unsigned long _fsamp; | |||
unsigned long _fsize; | |||
const char *_jname; | |||
}; | |||
class M_genpar : public ITC_mesg | |||
{ | |||
public: | |||
enum { WNOISE = 256, SINE = 512 }; | |||
M_genpar (void) : | |||
ITC_mesg (M_GENPAR) {} | |||
int _g_bits; | |||
float _a_noise; | |||
float _a_sine; | |||
float _f_sine; | |||
}; | |||
#endif |
@@ -0,0 +1,265 @@ | |||
// ---------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2003-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ---------------------------------------------------------------------- | |||
#ifndef __PRBSGEN_H | |||
#define __PRBSGEN_H | |||
#include <assert.h> | |||
#include <sys/types.h> | |||
#include <stdint.h> | |||
//--------------------------------------------------------------------------- | |||
// | |||
// Description: | |||
// Pseudo random binary sequence generator using polynomial | |||
// division in GF (2). | |||
// | |||
// There are two ways to built such a generator. Both use some | |||
// form of shift register. | |||
// | |||
// 1. The first type feeds back the parity (XOR) of the taps corresponding to | |||
// the non-zero elements of the polynomial into the input of the register. | |||
// This is the most efficient way to do it in hardware. | |||
// | |||
// 2. In the seond form, when the bit shifted out is 1, the contents of the | |||
// register are XORed with a bit pattern representing the polynomial. | |||
// This is the best way to do it in software. | |||
// | |||
// Mutatis mutandis the two forms are equivalent. Any sequence that can be | |||
// generated by one of the realisations can also be produced by the other. | |||
// This software obviously uses the second form. It can use any polynomial | |||
// up to (and including) a degree of 32. | |||
// | |||
// | |||
// set_poly (p) | |||
// | |||
// Defines the polynomial to be used. The value of p is found from the | |||
// sequence of coefficients (0 or 1) of the polynomial starting with the | |||
// constant term, and dropping the highest one | |||
// | |||
// 0 1 2 3 4 5 6 7 | |||
// Example: P = x^7 + x^6 + 1 --> 1 0 0 0 0 0 1 1 --> 1000001 --> 0x41 | |||
// | |||
// To emulate the first form described above, start with the highest | |||
// exponent and drop the constant term. | |||
// | |||
// 7 6 5 4 3 2 1 0 | |||
// Example: P = x^7 + x^6 + 1 --> 1 1 0 0 0 0 0 1 --> 1100000 --> 0x60 | |||
// | |||
// Also sets the state to all ones. | |||
// | |||
// | |||
// set_state (x) | |||
// | |||
// Sets the initial state to x. | |||
// | |||
// | |||
// step () | |||
// | |||
// Returns the next pseudo random bit. | |||
// | |||
// | |||
// sync_forw (x) | |||
// | |||
// This sets the generator in a state as if the last N (= degree) bits | |||
// were those defined by x (the LSB of x represents the oldest bit). | |||
// This can be used to synchronise a BER counter to a received bit stream, | |||
// or to set the initial state when emulating a generator of the first form | |||
// when the output is taken from the feedback. | |||
// | |||
// | |||
// sync_back (x) | |||
// | |||
// This sets the generator in a state so that the first N (= degree) output | |||
// bits will be those defined by x (the LSB of x will be the first output bit). | |||
// This can be used to set the initial state when emulating a generator of | |||
// the first form when the output is taken from the shifted out bit. | |||
// | |||
// | |||
//---------------------------------------------------------------------------== | |||
class Prbsgen | |||
{ | |||
public: | |||
enum | |||
{ | |||
// Some polynomials for maximum length seqeunces. | |||
G7 = 0x00000041, | |||
G8 = 0x0000008E, | |||
G15 = 0x00004001, | |||
G16 = 0x00008016, | |||
G23 = 0x00400010, | |||
G24 = 0x0080000D, | |||
G31 = 0x40000004, | |||
G32 = 0x80000057, | |||
}; | |||
Prbsgen (void); | |||
void set_poly (uint32_t poly); | |||
void set_stat (uint32_t stat); | |||
void sync_forw (uint32_t bits); | |||
void sync_back (uint32_t bits); | |||
int step (void); | |||
void crc_in (int b); | |||
int crc_out (void); | |||
uint32_t stat (void) const; | |||
uint32_t poly (void) const; | |||
uint32_t mask (void) const; | |||
uint32_t hbit (void) const; | |||
int degr (void) const; | |||
~Prbsgen (void); | |||
private: | |||
uint32_t _stat; | |||
uint32_t _poly; | |||
uint32_t _mask; | |||
uint32_t _hbit; | |||
int _degr; | |||
}; | |||
inline Prbsgen::Prbsgen (void) | |||
: _stat (0), _poly (0), _mask (0), _degr (0) | |||
{ | |||
} | |||
inline Prbsgen::~Prbsgen (void) | |||
{ | |||
} | |||
inline void Prbsgen::set_poly (uint32_t poly) | |||
{ | |||
assert (poly != 0); | |||
_poly = poly; | |||
_mask = 0; | |||
_degr = 0; | |||
while (_mask < _poly) | |||
{ | |||
_mask = (_mask << 1) | 1; | |||
_degr += 1; | |||
} | |||
_stat = _mask; | |||
_hbit = (_mask >> 1) + 1; | |||
} | |||
inline void Prbsgen::set_stat (uint32_t stat) | |||
{ | |||
assert (_poly != 0); | |||
_stat = stat & _mask; | |||
assert (_stat != 0); | |||
} | |||
inline int Prbsgen::step (void) | |||
{ | |||
int bit; | |||
assert (_poly != 0); | |||
bit = _stat & 1; | |||
_stat >>= 1; | |||
if (bit) _stat ^= _poly; | |||
return bit; | |||
} | |||
inline void Prbsgen::sync_forw (uint32_t bits) | |||
{ | |||
assert (_poly != 0); | |||
for (int i = 0; i < _degr; i++) | |||
{ | |||
_stat >>= 1; | |||
if (bits & 1) _stat ^= _poly; | |||
bits >>= 1; | |||
} | |||
} | |||
inline void Prbsgen::sync_back (uint32_t bits) | |||
{ | |||
assert (_poly != 0); | |||
_stat = 0; | |||
for (int h = _hbit; h; h >>= 1) | |||
{ | |||
if (bits & h) _stat ^= _poly; | |||
_stat <<= 1; | |||
} | |||
_stat ^= bits; | |||
_stat &= _mask; | |||
} | |||
inline void Prbsgen::crc_in (int b) | |||
{ | |||
int bit; | |||
assert (_poly != 0); | |||
bit = (_stat & 1) ^ b; | |||
_stat >>= 1; | |||
if (bit) _stat ^= _poly; | |||
} | |||
inline int Prbsgen::crc_out (void) | |||
{ | |||
int bit; | |||
assert (_poly != 0); | |||
bit = (_stat & 1); | |||
_stat >>= 1; | |||
return bit; | |||
} | |||
inline uint32_t Prbsgen::stat (void) const { return _stat; } | |||
inline uint32_t Prbsgen::poly (void) const { return _poly; } | |||
inline uint32_t Prbsgen::mask (void) const { return _mask; } | |||
inline uint32_t Prbsgen::hbit (void) const { return _hbit; } | |||
inline int Prbsgen::degr (void) const { return _degr; } | |||
#endif |
@@ -0,0 +1,153 @@ | |||
// ---------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2003-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ---------------------------------------------------------------------- | |||
#include <math.h> | |||
#include <time.h> | |||
#include "rngen.h" | |||
const double Rngen::_p31 = 2147483648.0; | |||
const double Rngen::_p32 = 4294967296.0; | |||
const float Rngen::_p31f = 2147483648.0f; | |||
const float Rngen::_p32f = 4294967296.0f; | |||
Rngen::Rngen (void) | |||
{ | |||
init (0); | |||
} | |||
Rngen::~Rngen (void) | |||
{ | |||
} | |||
void Rngen::init (uint32_t s) | |||
{ | |||
int i, j; | |||
Prbsgen G; | |||
if (s == 0) s = time (0); | |||
G.set_poly (Prbsgen::G32); | |||
G.set_stat (s); | |||
for (i = 0; i < 55; i++) | |||
{ | |||
G.step (); | |||
j = G.stat () & 4095; | |||
while (j--) G.step (); | |||
_a [i] = G.stat (); | |||
} | |||
_i = 0; | |||
_md = false; | |||
_mf = false; | |||
} | |||
double Rngen::grand (void) | |||
{ | |||
double a, b, r; | |||
if (_md) | |||
{ | |||
_md = false; | |||
return _vd; | |||
} | |||
do | |||
{ | |||
a = irand () / _p31 - 1.0; | |||
b = irand () / _p31 - 1.0; | |||
r = a * a + b * b; | |||
} | |||
while ((r > 1.0) || (r < 1e-20)); | |||
r = sqrt (-2.0 * log (r) / r); | |||
_md = true; | |||
_vd = r * b; | |||
return r * a; | |||
} | |||
void Rngen::grand (double *x, double *y) | |||
{ | |||
double a, b, r; | |||
do | |||
{ | |||
a = irand () / _p31 - 1.0; | |||
b = irand () / _p31 - 1.0; | |||
r = a * a + b * b; | |||
} | |||
while ((r > 1.0) || (r < 1e-20)); | |||
r = sqrt (-log (r) / r); | |||
*x = r * a; | |||
*y = r * b; | |||
} | |||
float Rngen::grandf (void) | |||
{ | |||
float a, b, r; | |||
if (_mf) | |||
{ | |||
_mf = false; | |||
return _vf; | |||
} | |||
do | |||
{ | |||
a = irand () / _p31f - 1.0f; | |||
b = irand () / _p31f - 1.0f; | |||
r = a * a + b * b; | |||
} | |||
while ((r > 1.0f) || (r < 1e-20f)); | |||
r = sqrtf (-2.0f * logf (r) / r); | |||
_mf = true; | |||
_vf = r * b; | |||
return r * a; | |||
} | |||
void Rngen::grandf (float *x, float *y) | |||
{ | |||
float a, b, r; | |||
do | |||
{ | |||
a = irand () / _p31f - 1.0f; | |||
b = irand () / _p31f - 1.0f; | |||
r = a * a + b * b; | |||
} | |||
while ((r > 1.0f) || (r < 1e-20f)); | |||
r = sqrtf (-logf (r) / r); | |||
*x = r * a; | |||
*y = r * b; | |||
} |
@@ -0,0 +1,74 @@ | |||
// ---------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2003-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ---------------------------------------------------------------------- | |||
#ifndef __RNGEN_H | |||
#define __RNGEN_H | |||
#include "prbsgen.h" | |||
class Rngen | |||
{ | |||
public: | |||
Rngen (void); | |||
void init (uint32_t seed); | |||
uint32_t irand (void) | |||
{ | |||
uint32_t r; | |||
if (++_i == 55) _i = 0; | |||
if (_i < 24) r = _a [_i] += _a [_i + 31]; | |||
else r = _a [_i] += _a [_i - 24]; | |||
return r; | |||
} | |||
double urand (void) { return irand () / _p32; } | |||
double grand (void); | |||
void grand (double *x, double *y); | |||
float urandf (void) { return irand () / _p32f; } | |||
float grandf (void); | |||
void grandf (float *x, float *y); | |||
~Rngen (void); | |||
Rngen (const Rngen&); // disabled, not to be used | |||
Rngen& operator=(const Rngen&); // disabled, not to be used | |||
private: | |||
uint32_t _a [55]; | |||
int _i; | |||
bool _md; | |||
bool _mf; | |||
double _vd; | |||
float _vf; | |||
static const double _p31; | |||
static const double _p32; | |||
static const float _p31f; | |||
static const float _p32f; | |||
}; | |||
#endif |
@@ -0,0 +1,209 @@ | |||
// ------------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ------------------------------------------------------------------------- | |||
#ifndef __SPECTWIN_H | |||
#define __SPECTWIN_H | |||
#include <clxclient.h> | |||
#include <clthreads.h> | |||
#include <fftw3.h> | |||
#include "styles.h" | |||
#define XPOS 100 | |||
#define YPOS 100 | |||
#define XMIN 600 | |||
#define YMIN 430 | |||
#define XDEF 600 | |||
#define YDEF 450 | |||
#define XMAX 1200 | |||
#define YMAX 900 | |||
#define LMAR 40 | |||
#define RMAR 80 | |||
#define TMAR 8 | |||
#define BMAR 24 | |||
class Spectdata | |||
{ | |||
public: | |||
enum { MK1_SET = 1, MK1_NSE = 2, MK2_SET = 4, MK2_NSE = 8, RESET = 16, PEAKH = 32, FREEZE = 64, YP_VAL = 256, YM_VAL = 512 }; | |||
Spectdata (int size) | |||
{ | |||
_yp = new float [size]; | |||
_ym = new float [size]; | |||
} | |||
~Spectdata (void) | |||
{ | |||
delete[] _yp; | |||
delete[] _ym; | |||
} | |||
int _npix; | |||
int _bits; | |||
int _avcnt; | |||
int _avmax; | |||
float _bw; | |||
float _f0; | |||
float _f1; | |||
float _mk1f; | |||
float _mk1p; | |||
float _mk2f; | |||
float _mk2p; | |||
char *_xf; | |||
float *_yp; | |||
float *_ym; | |||
}; | |||
class Spectwin : public X_window, public X_callback | |||
{ | |||
public: | |||
Spectwin (X_window *parent, X_resman *xres, ITC_ctrl *audio); | |||
~Spectwin (void); | |||
bool running (void) const { return _running; } | |||
void handle_trig (void); | |||
void handle_term (void) { _running = 0; } | |||
void handle_mesg (ITC_mesg *); | |||
private: | |||
enum | |||
{ | |||
IP1, IP2, IP3, IP4, | |||
IP5, IP6, IP7, IP8, | |||
BANDW, VIDAV, PEAKH, FREEZ, | |||
MCLR, MPEAK, MNSE, | |||
FMIN, FMAX, FCENT, FSPAN, | |||
AMAX, ASPAN, | |||
BTUP, BTDN, | |||
OP1, OP2, OP3, OP4, | |||
OP5, OP6, OP7, OP8, | |||
NSACT, SIACT, | |||
NSLEV, SILEV, SFREQ, | |||
NBUTT | |||
}; | |||
enum | |||
{ | |||
FFT_MIN = 256, | |||
FFT_MAX = 1024 * 256, | |||
BUF_LEN = 2 * FFT_MAX, | |||
INP_MAX = BUF_LEN - FFT_MAX / 2, | |||
INP_LEN = 4096 | |||
}; | |||
virtual void handle_event (XEvent *xe); | |||
virtual void handle_callb (int, X_window*, _XEvent*); | |||
void message (XClientMessageEvent *); | |||
void expose (XExposeEvent *); | |||
void resize (XConfigureEvent *); | |||
void redraw (void); | |||
void update (void); | |||
void bpress (XButtonEvent *); | |||
void motion (XPointerMovedEvent *); | |||
void brelse (XButtonEvent *); | |||
void set_fsamp (float fsamp, bool symm); | |||
void set_input (int i); | |||
void set_output (int i); | |||
void set_param (int i); | |||
void mod_param (bool inc); | |||
void set_bw (float); | |||
void set_f0 (float); | |||
void set_f1 (float); | |||
void set_fc (float); | |||
void set_fs (float); | |||
void set_a1 (float); | |||
void set_ar (float); | |||
void set_a_ns (float); | |||
void set_a_si (float); | |||
void set_f_si (float); | |||
void send_genp (void); | |||
void set_mark (float f, bool nse); | |||
void clr_mark (void); | |||
void show_param (void); | |||
void plot_fscale (void); | |||
void plot_ascale (void); | |||
void plot_clear (void); | |||
void plot_grid (void); | |||
void plot_spect (Spectdata *); | |||
void plot_annot (Spectdata *); | |||
void alloc_fft (Spectdata *); | |||
void calc_spect (Spectdata *); | |||
float calcfreq (int x); | |||
float conv0 (fftwf_complex *); | |||
float conv1 (fftwf_complex *); | |||
void calc_noise (float *f, float *p); | |||
void calc_peak (float *f, float *p, float r); | |||
void print_note (char *s, float f); | |||
int _xs, _ys; | |||
int _running; | |||
Atom _atoms [2]; | |||
Atom _wmpro; | |||
X_window *_plotwin; | |||
Pixmap _plotmap; | |||
GC _plotgct; | |||
X_button *_butt [NBUTT]; | |||
X_textip *_txt1; | |||
Spectdata *_spect; | |||
ITC_ctrl *_audio; | |||
int _input; | |||
int _drag; | |||
int _xd, _yd; | |||
int _p_ind; | |||
float _p_val; | |||
float _fsamp; | |||
float _funit; | |||
const char *_fform; | |||
float _bmin, _bmax, _bw; | |||
float _fmin, _fmax, _f0, _f1, _fc, _fm, _df; | |||
float _amin, _amax, _a0, _a1, _da; | |||
float _a_ns, _a_si, _f_si, _a_pu; | |||
int _g_bits; | |||
int _ngx, _grx [40]; | |||
int _ngy, _gry [20]; | |||
fftwf_complex *_trbuf; | |||
fftwf_plan _fftplan; | |||
float *_ipbuf; | |||
float *_fftbuf; | |||
float *_power; | |||
int _fftlen; | |||
int _ipmod; | |||
int _ipcnt; | |||
float _ptot; | |||
const static char *_formats [9]; | |||
const static char *_notes [12]; | |||
friend class JaaaPlugin; | |||
}; | |||
#endif |
@@ -0,0 +1,135 @@ | |||
// ------------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ------------------------------------------------------------------------- | |||
#include "styles.h" | |||
struct colors Colors; | |||
struct fonts Fonts; | |||
struct xft_colors XftColors; | |||
struct xft_fonts XftFonts; | |||
X_button_style Bst0, Bst1, BstA, BstB, BstM; | |||
X_textln_style Tst0, Tst1; | |||
void init_styles (X_display *disp, X_resman *xrm) | |||
{ | |||
Colors.black = disp->blackpixel (); | |||
Colors.white = disp->whitepixel (); | |||
Colors.main_bg = disp->alloc_color (xrm->get (".color.main.bg", "#e4e0d4"), Colors.white); | |||
Colors.main_ds = disp->alloc_color (xrm->get (".color.main.ds", "gray20"), Colors.black); | |||
Colors.main_ls = disp->alloc_color (xrm->get (".color.main.ls", "white"), Colors.white); | |||
Colors.text_ed = disp->alloc_color (xrm->get (".color.text.ed", "yellow"), Colors.white); | |||
Colors.text_ca = disp->alloc_color (xrm->get (".color.text.ca", "black"), Colors.black); | |||
Colors.spect_bg = disp->alloc_color (xrm->get (".color.spect.bg", "white"), Colors.white); | |||
Colors.spect_gr = disp->alloc_color (xrm->get (".color.spect.gr", "gray80"), Colors.white); | |||
Colors.spect_mk = disp->alloc_color (xrm->get (".color.spect.mk", "red"), Colors.black); | |||
Colors.spect_trA = disp->alloc_color (xrm->get (".color.spect.trA", "blue"), Colors.black); | |||
Colors.spect_pkA = disp->alloc_color (xrm->get (".color.spect.pkA", "#A0A0FF"), Colors.black); | |||
Colors.spect_trB = disp->alloc_color (xrm->get (".color.spect.trB", "blue"), Colors.black); | |||
Colors.spect_pkB = disp->alloc_color (xrm->get (".color.spect.pkB", "#A0A0FF"), Colors.black); | |||
Colors.spect_trM = disp->alloc_color (xrm->get (".color.spect.trM", "darkgreen"), Colors.white); | |||
Colors.butt_bg0 = disp->alloc_color (xrm->get (".color.butt.bg0", "#d0c8c0"), Colors.white); | |||
Colors.butt_bg1 = disp->alloc_color (xrm->get (".color.butt.bg1", "yellow"), Colors.white); | |||
Colors.butt_bg2 = disp->alloc_color (xrm->get (".color.butt.bg2", "green"), Colors.white); | |||
Colors.butt_bgA = disp->alloc_color (xrm->get (".color.butt.bgA", "red"), Colors.black); | |||
Colors.butt_bgB = disp->alloc_color (xrm->get (".color.butt.bgB", "blue"), Colors.black); | |||
Colors.butt_bgM = disp->alloc_color (xrm->get (".color.butt.bgM", "green"), Colors.white); | |||
XftColors.white = disp->alloc_xftcolor ("white", 0); | |||
XftColors.black = disp->alloc_xftcolor ("black", 0); | |||
XftColors.main_fg = disp->alloc_xftcolor (xrm->get (".color.main.fg", "black"), XftColors.black); | |||
XftColors.text_fg = disp->alloc_xftcolor (xrm->get (".color.text.fg", "black"), XftColors.black); | |||
XftColors.spect_fg = disp->alloc_xftcolor (xrm->get (".color.spect.fg", "blue"), XftColors.black); | |||
XftColors.spect_sc = disp->alloc_xftcolor (xrm->get (".color.spect.sc", "black"), XftColors.black); | |||
XftColors.spect_an = disp->alloc_xftcolor (xrm->get (".color.spect.an", "red"), XftColors.black); | |||
XftColors.butt_fg0 = disp->alloc_xftcolor (xrm->get (".color.butt.fg0", "black"), XftColors.black); | |||
XftColors.butt_fg1 = disp->alloc_xftcolor (xrm->get (".color.butt.fg1", "black"), XftColors.black); | |||
XftColors.butt_fg2 = disp->alloc_xftcolor (xrm->get (".color.butt.fg2", "black"), XftColors.black); | |||
XftColors.butt_fgA = disp->alloc_xftcolor (xrm->get (".color.butt.fgA", "white"), XftColors.white); | |||
XftColors.butt_fgB = disp->alloc_xftcolor (xrm->get (".color.butt.fgB", "white"), XftColors.white); | |||
XftColors.butt_fgM = disp->alloc_xftcolor (xrm->get (".color.butt.fgM", "black"), XftColors.black); | |||
XftFonts.about1 = disp->alloc_xftfont (xrm->get (".font.about1", "times:pixelsize=24")); | |||
XftFonts.about2 = disp->alloc_xftfont (xrm->get (".font.about2", "times:pixelsize=14")); | |||
XftFonts.button = disp->alloc_xftfont (xrm->get (".font.button", "luxi:pixelsize=11")); | |||
XftFonts.labels = disp->alloc_xftfont (xrm->get (".font.labels", "luxi:pixelsize=11")); | |||
XftFonts.scales = disp->alloc_xftfont (xrm->get (".font.scales", "luxi:pixelsize=10")); | |||
Bst0.font = XftFonts.button; | |||
Bst0.color.bg [0] = Colors.butt_bg0; | |||
Bst0.color.fg [0] = XftColors.butt_fg0; | |||
Bst0.color.bg [1] = Colors.butt_bg1; | |||
Bst0.color.fg [1] = XftColors.butt_fg1; | |||
Bst0.color.bg [2] = Colors.butt_bg2; | |||
Bst0.color.fg [2] = XftColors.butt_fg2; | |||
Bst0.color.shadow.bgnd = Colors.main_bg; | |||
Bst0.color.shadow.lite = Colors.main_ls; | |||
Bst0.color.shadow.dark = Colors.main_ds; | |||
Bst0.size.x = 17; | |||
Bst0.size.y = 17; | |||
Bst0.type = X_button_style::RAISED; | |||
Bst1.font = XftFonts.button; | |||
Bst1.color.bg [0] = Colors.butt_bg0; | |||
Bst1.color.fg [0] = XftColors.butt_fg0; | |||
Bst1.color.bg [1] = Colors.butt_bg1; | |||
Bst1.color.fg [1] = XftColors.butt_fg1; | |||
Bst1.color.bg [2] = Colors.butt_bg2; | |||
Bst1.color.fg [2] = XftColors.butt_fg2; | |||
Bst1.color.shadow.bgnd = Colors.main_bg; | |||
Bst1.color.shadow.lite = Colors.main_ls; | |||
Bst1.color.shadow.dark = Colors.main_ds; | |||
Bst1.size.x = 17; | |||
Bst1.size.y = 17; | |||
Bst1.type = X_button_style::RAISED;// | X_button_style::LED; | |||
BstA = Bst0; | |||
BstA.color.bg [1] = Colors.butt_bgA; | |||
BstA.color.fg [1] = XftColors.butt_fgA; | |||
BstB = Bst0; | |||
BstB.color.bg [1] = Colors.butt_bgB; | |||
BstB.color.fg [1] = XftColors.butt_fgB; | |||
BstM = Bst0; | |||
BstM.color.bg [1] = Colors.butt_bgM; | |||
BstM.color.fg [1] = XftColors.butt_fgM; | |||
Tst0.font = XftFonts.labels; | |||
Tst0.color.normal.bgnd = Colors.white; | |||
Tst0.color.normal.text = XftColors.text_fg; | |||
Tst0.color.shadow.lite = Colors.main_ls; | |||
Tst0.color.shadow.dark = Colors.main_ds; | |||
Tst0.color.shadow.bgnd = Colors.main_bg; | |||
Tst1.font = XftFonts.labels; | |||
Tst1.color.normal.bgnd = Colors.main_bg; | |||
Tst1.color.normal.text = XftColors.main_fg; | |||
Tst1.color.focus.bgnd = Colors.text_ed; | |||
Tst1.color.focus.text = XftColors.main_fg; | |||
Tst1.color.focus.line = Colors.text_ca; | |||
Tst1.color.shadow.lite = Colors.main_ls; | |||
Tst1.color.shadow.dark = Colors.main_ds; | |||
Tst1.color.shadow.bgnd = Colors.main_bg; | |||
} | |||
@@ -0,0 +1,103 @@ | |||
// ------------------------------------------------------------------------- | |||
// | |||
// Copyright (C) 2004-2013 Fons Adriaensen <fons@linuxaudio.org> | |||
// | |||
// This program is free software; you can redistribute it and/or modify | |||
// it under the terms of the GNU General Public License as published by | |||
// the Free Software Foundation; either version 2 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU General Public License | |||
// along with this program; if not, write to the Free Software | |||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
// | |||
// ------------------------------------------------------------------------- | |||
#ifndef __STYLES_H | |||
#define __STYLES_H | |||
#include <clxclient.h> | |||
struct colors | |||
{ | |||
unsigned long white; | |||
unsigned long black; | |||
unsigned long main_bg; | |||
unsigned long main_ds; | |||
unsigned long main_ls; | |||
unsigned long text_ed; | |||
unsigned long text_ca; | |||
unsigned long spect_bg; | |||
unsigned long spect_gr; | |||
unsigned long spect_mk; | |||
unsigned long spect_trA; | |||
unsigned long spect_pkA; | |||
unsigned long spect_trB; | |||
unsigned long spect_pkB; | |||
unsigned long spect_trM; | |||
unsigned long butt_bg0; | |||
unsigned long butt_bg1; | |||
unsigned long butt_bg2; | |||
unsigned long butt_bgA; | |||
unsigned long butt_bgB; | |||
unsigned long butt_bgM; | |||
}; | |||
struct fonts | |||
{ | |||
}; | |||
struct xft_colors | |||
{ | |||
XftColor *white; | |||
XftColor *black; | |||
XftColor *main_fg; | |||
XftColor *text_fg; | |||
XftColor *spect_fg; | |||
XftColor *spect_sc; | |||
XftColor *spect_an; | |||
XftColor *butt_fg0; | |||
XftColor *butt_fg1; | |||
XftColor *butt_fg2; | |||
XftColor *butt_fgA; | |||
XftColor *butt_fgB; | |||
XftColor *butt_fgM; | |||
}; | |||
struct xft_fonts | |||
{ | |||
XftFont *about1; | |||
XftFont *about2; | |||
XftFont *button; | |||
XftFont *labels; | |||
XftFont *scales; | |||
}; | |||
extern struct colors Colors; | |||
extern struct fonts Fonts; | |||
extern struct xft_colors XftColors; | |||
extern struct xft_fonts XftFonts; | |||
extern X_button_style Bst0, Bst1, BstA, BstB, BstM; | |||
extern X_textln_style Tst0, Tst1; | |||
extern void init_styles (X_display *disp, X_resman *xrm); | |||
#define PROGNAME "Jack/Alsa Audio Analyser" | |||
#endif |