Mercurial > hg > svapp
view audioio/AudioJACKTarget.cpp @ 5:2edc0757ca75
* Fixes to playback of short looped files, of synthesised content within looped
sections, and a few other fixes
author | Chris Cannam |
---|---|
date | Thu, 26 Jan 2006 11:56:09 +0000 |
parents | df5923e33d01 |
children | 89bb89894ad6 |
line wrap: on
line source
/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ /* A waveform viewer and audio annotation editor. Chris Cannam, Queen Mary University of London, 2005-2006 This is experimental software. Not for distribution. */ #ifdef HAVE_JACK #include "AudioJACKTarget.h" #include "AudioCallbackPlaySource.h" #include <iostream> //#define DEBUG_AUDIO_JACK_TARGET 1 AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) : AudioCallbackPlayTarget(source), m_client(0), m_bufferSize(0), m_sampleRate(0) { char name[20]; strcpy(name, "Sonic Visualiser"); m_client = jack_client_new(name); if (!m_client) { sprintf(name, "Sonic Visualiser (%d)", (int)getpid()); m_client = jack_client_new(name); if (!m_client) { std::cerr << "ERROR: AudioJACKTarget: Failed to connect to JACK server" << std::endl; } } if (!m_client) return; m_bufferSize = jack_get_buffer_size(m_client); m_sampleRate = jack_get_sample_rate(m_client); jack_set_process_callback(m_client, processStatic, this); if (jack_activate(m_client)) { std::cerr << "ERROR: AudioJACKTarget: Failed to activate JACK client" << std::endl; } if (m_source) { sourceModelReplaced(); } } AudioJACKTarget::~AudioJACKTarget() { if (m_client) { jack_deactivate(m_client); jack_client_close(m_client); } } bool AudioJACKTarget::isOK() const { return (m_client != 0); } int AudioJACKTarget::processStatic(jack_nframes_t nframes, void *arg) { return ((AudioJACKTarget *)arg)->process(nframes); } void AudioJACKTarget::sourceModelReplaced() { m_mutex.lock(); m_source->setTargetBlockSize(m_bufferSize); m_source->setTargetSampleRate(m_sampleRate); size_t channels = m_source->getSourceChannelCount(); if (channels == m_outputs.size() || !m_client) { m_mutex.unlock(); return; } const char **ports = jack_get_ports(m_client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); size_t physicalPortCount = 0; while (ports[physicalPortCount]) ++physicalPortCount; #ifdef DEBUG_AUDIO_JACK_TARGET std::cerr << "AudioJACKTarget::sourceModelReplaced: have " << channels << " channels and " << physicalPortCount << " physical ports" << std::endl; #endif while (m_outputs.size() < channels) { char name[20]; jack_port_t *port; sprintf(name, "out %d", m_outputs.size() + 1); port = jack_port_register(m_client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!port) { std::cerr << "ERROR: AudioJACKTarget: Failed to create JACK output port " << m_outputs.size() << std::endl; } else { m_source->setTargetPlayLatency(jack_port_get_latency(port)); } if (m_outputs.size() < physicalPortCount) { jack_connect(m_client, jack_port_name(port), ports[m_outputs.size()]); } m_outputs.push_back(port); } while (m_outputs.size() > channels) { std::vector<jack_port_t *>::iterator itr = m_outputs.end(); --itr; jack_port_t *port = *itr; if (port) jack_port_unregister(m_client, port); m_outputs.erase(itr); } m_mutex.unlock(); } int AudioJACKTarget::process(jack_nframes_t nframes) { if (!m_mutex.tryLock()) { return 0; } if (m_outputs.empty()) { m_mutex.unlock(); return 0; } #ifdef DEBUG_AUDIO_JACK_TARGET std::cout << "AudioJACKTarget::process(" << nframes << "): have a source" << std::endl; #endif #ifdef DEBUG_AUDIO_JACK_TARGET if (m_bufferSize != nframes) { std::cerr << "WARNING: m_bufferSize != nframes (" << m_bufferSize << " != " << nframes << ")" << std::endl; } #endif float **buffers = (float **)alloca(m_outputs.size() * sizeof(float *)); for (size_t ch = 0; ch < m_outputs.size(); ++ch) { buffers[ch] = (float *)jack_port_get_buffer(m_outputs[ch], nframes); } if (m_source) { m_source->getSourceSamples(nframes, buffers); } else { for (size_t ch = 0; ch < m_outputs.size(); ++ch) { for (size_t i = 0; i < nframes; ++i) { buffers[ch][i] = 0.0; } } } float peakLeft = 0.0, peakRight = 0.0; for (size_t ch = 0; ch < m_outputs.size(); ++ch) { float peak = 0.0; for (size_t i = 0; i < nframes; ++i) { buffers[ch][i] *= m_outputGain; float sample = fabsf(buffers[ch][i]); if (sample > peak) peak = sample; } if (ch == 0) peakLeft = peak; if (ch > 0 || m_outputs.size() == 1) peakRight = peak; } if (m_source) { m_source->setOutputLevels(peakLeft, peakRight); } m_mutex.unlock(); return 0; } #ifdef INCLUDE_MOCFILES #include "AudioJACKTarget.moc.cpp" #endif #endif /* HAVE_JACK */