annotate audioio/AudioJACKTarget.cpp @ 0:db6fcbd4405c

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children df5923e33d01
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@0 5 Chris Cannam, Queen Mary University of London, 2005
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 #ifdef HAVE_JACK
Chris@0 11
Chris@0 12 #include "AudioJACKTarget.h"
Chris@0 13 #include "AudioCallbackPlaySource.h"
Chris@0 14
Chris@0 15 #include <iostream>
Chris@0 16
Chris@0 17 //#define DEBUG_AUDIO_JACK_TARGET 1
Chris@0 18
Chris@0 19 AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) :
Chris@0 20 AudioCallbackPlayTarget(source),
Chris@0 21 m_client(0),
Chris@0 22 m_bufferSize(0),
Chris@0 23 m_sampleRate(0)
Chris@0 24 {
Chris@0 25 char name[20];
Chris@0 26 strcpy(name, "Sonic Visualiser");
Chris@0 27 m_client = jack_client_new(name);
Chris@0 28
Chris@0 29 if (!m_client) {
Chris@0 30 sprintf(name, "Sonic Visualiser (%d)", (int)getpid());
Chris@0 31 m_client = jack_client_new(name);
Chris@0 32 if (!m_client) {
Chris@0 33 std::cerr
Chris@0 34 << "ERROR: AudioJACKTarget: Failed to connect to JACK server"
Chris@0 35 << std::endl;
Chris@0 36 }
Chris@0 37 }
Chris@0 38
Chris@0 39 if (!m_client) return;
Chris@0 40
Chris@0 41 m_bufferSize = jack_get_buffer_size(m_client);
Chris@0 42 m_sampleRate = jack_get_sample_rate(m_client);
Chris@0 43
Chris@0 44 jack_set_process_callback(m_client, processStatic, this);
Chris@0 45
Chris@0 46 if (jack_activate(m_client)) {
Chris@0 47 std::cerr << "ERROR: AudioJACKTarget: Failed to activate JACK client"
Chris@0 48 << std::endl;
Chris@0 49 }
Chris@0 50
Chris@0 51 if (m_source) {
Chris@0 52 sourceModelReplaced();
Chris@0 53 }
Chris@0 54 }
Chris@0 55
Chris@0 56 AudioJACKTarget::~AudioJACKTarget()
Chris@0 57 {
Chris@0 58 if (m_client) {
Chris@0 59 jack_deactivate(m_client);
Chris@0 60 jack_client_close(m_client);
Chris@0 61 }
Chris@0 62 }
Chris@0 63
Chris@0 64 bool
Chris@0 65 AudioJACKTarget::isOK() const
Chris@0 66 {
Chris@0 67 return (m_client != 0);
Chris@0 68 }
Chris@0 69
Chris@0 70 int
Chris@0 71 AudioJACKTarget::processStatic(jack_nframes_t nframes, void *arg)
Chris@0 72 {
Chris@0 73 return ((AudioJACKTarget *)arg)->process(nframes);
Chris@0 74 }
Chris@0 75
Chris@0 76 void
Chris@0 77 AudioJACKTarget::sourceModelReplaced()
Chris@0 78 {
Chris@0 79 m_mutex.lock();
Chris@0 80
Chris@0 81 m_source->setTargetBlockSize(m_bufferSize);
Chris@0 82 m_source->setTargetSampleRate(m_sampleRate);
Chris@0 83
Chris@0 84 size_t channels = m_source->getSourceChannelCount();
Chris@0 85
Chris@0 86 if (channels == m_outputs.size() || !m_client) {
Chris@0 87 m_mutex.unlock();
Chris@0 88 return;
Chris@0 89 }
Chris@0 90
Chris@0 91 const char **ports =
Chris@0 92 jack_get_ports(m_client, NULL, NULL,
Chris@0 93 JackPortIsPhysical | JackPortIsInput);
Chris@0 94 size_t physicalPortCount = 0;
Chris@0 95 while (ports[physicalPortCount]) ++physicalPortCount;
Chris@0 96
Chris@0 97 #ifdef DEBUG_AUDIO_JACK_TARGET
Chris@0 98 std::cerr << "AudioJACKTarget::sourceModelReplaced: have " << channels << " channels and " << physicalPortCount << " physical ports" << std::endl;
Chris@0 99 #endif
Chris@0 100
Chris@0 101 while (m_outputs.size() < channels) {
Chris@0 102
Chris@0 103 char name[20];
Chris@0 104 jack_port_t *port;
Chris@0 105
Chris@0 106 sprintf(name, "out %d", m_outputs.size() + 1);
Chris@0 107
Chris@0 108 port = jack_port_register(m_client,
Chris@0 109 name,
Chris@0 110 JACK_DEFAULT_AUDIO_TYPE,
Chris@0 111 JackPortIsOutput,
Chris@0 112 0);
Chris@0 113
Chris@0 114 if (!port) {
Chris@0 115 std::cerr
Chris@0 116 << "ERROR: AudioJACKTarget: Failed to create JACK output port "
Chris@0 117 << m_outputs.size() << std::endl;
Chris@0 118 } else {
Chris@0 119 m_source->setTargetPlayLatency(jack_port_get_latency(port));
Chris@0 120 }
Chris@0 121
Chris@0 122 if (m_outputs.size() < physicalPortCount) {
Chris@0 123 jack_connect(m_client, jack_port_name(port), ports[m_outputs.size()]);
Chris@0 124 }
Chris@0 125
Chris@0 126 m_outputs.push_back(port);
Chris@0 127 }
Chris@0 128
Chris@0 129 while (m_outputs.size() > channels) {
Chris@0 130 std::vector<jack_port_t *>::iterator itr = m_outputs.end();
Chris@0 131 --itr;
Chris@0 132 jack_port_t *port = *itr;
Chris@0 133 if (port) jack_port_unregister(m_client, port);
Chris@0 134 m_outputs.erase(itr);
Chris@0 135 }
Chris@0 136
Chris@0 137 m_mutex.unlock();
Chris@0 138 }
Chris@0 139
Chris@0 140 int
Chris@0 141 AudioJACKTarget::process(jack_nframes_t nframes)
Chris@0 142 {
Chris@0 143 if (!m_mutex.tryLock()) {
Chris@0 144 return 0;
Chris@0 145 }
Chris@0 146
Chris@0 147 if (m_outputs.empty()) {
Chris@0 148 m_mutex.unlock();
Chris@0 149 return 0;
Chris@0 150 }
Chris@0 151
Chris@0 152 #ifdef DEBUG_AUDIO_JACK_TARGET
Chris@0 153 std::cout << "AudioJACKTarget::process(" << nframes << "): have a source" << std::endl;
Chris@0 154 #endif
Chris@0 155
Chris@0 156 #ifdef DEBUG_AUDIO_JACK_TARGET
Chris@0 157 if (m_bufferSize != nframes) {
Chris@0 158 std::cerr << "WARNING: m_bufferSize != nframes (" << m_bufferSize << " != " << nframes << ")" << std::endl;
Chris@0 159 }
Chris@0 160 #endif
Chris@0 161
Chris@0 162 float **buffers = (float **)alloca(m_outputs.size() * sizeof(float *));
Chris@0 163
Chris@0 164 for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
Chris@0 165 buffers[ch] = (float *)jack_port_get_buffer(m_outputs[ch], nframes);
Chris@0 166 }
Chris@0 167
Chris@0 168 if (m_source) {
Chris@0 169 m_source->getSourceSamples(nframes, buffers);
Chris@0 170 } else {
Chris@0 171 for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
Chris@0 172 for (size_t i = 0; i < nframes; ++i) {
Chris@0 173 buffers[ch][i] = 0.0;
Chris@0 174 }
Chris@0 175 }
Chris@0 176 }
Chris@0 177
Chris@0 178 float peakLeft = 0.0, peakRight = 0.0;
Chris@0 179
Chris@0 180 for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
Chris@0 181
Chris@0 182 float peak = 0.0;
Chris@0 183
Chris@0 184 for (size_t i = 0; i < nframes; ++i) {
Chris@0 185 buffers[ch][i] *= m_outputGain;
Chris@0 186 float sample = fabsf(buffers[ch][i]);
Chris@0 187 if (sample > peak) peak = sample;
Chris@0 188 }
Chris@0 189
Chris@0 190 if (ch == 0) peakLeft = peak;
Chris@0 191 if (ch > 0 || m_outputs.size() == 1) peakRight = peak;
Chris@0 192 }
Chris@0 193
Chris@0 194 if (m_source) {
Chris@0 195 m_source->setOutputLevels(peakLeft, peakRight);
Chris@0 196 }
Chris@0 197
Chris@0 198 m_mutex.unlock();
Chris@0 199 return 0;
Chris@0 200 }
Chris@0 201
Chris@0 202
Chris@0 203 #ifdef INCLUDE_MOCFILES
Chris@0 204 #include "AudioJACKTarget.moc.cpp"
Chris@0 205 #endif
Chris@0 206
Chris@0 207 #endif /* HAVE_JACK */
Chris@0 208