diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2016-07-13 11:25:59 +0200 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2016-07-13 11:25:59 +0200 |
commit | 633bac9e82aef192a803666aaf3d3dcff920ac0c (patch) | |
tree | b4b253162c0dcdbace27807e11e5915ebce1cfab | |
parent | 7557e5d1713337f4acc3f531e5b88a1195476eec (diff) |
Use the latency reported by the engine in the jack and wavfile output modules.
-rw-r--r-- | drumgizmo/drumgizmoc.cc | 1 | ||||
-rw-r--r-- | drumgizmo/jackclient.cc | 20 | ||||
-rw-r--r-- | drumgizmo/jackclient.h | 3 | ||||
-rw-r--r-- | drumgizmo/output/jackaudio.cc | 36 | ||||
-rw-r--r-- | drumgizmo/output/jackaudio.h | 4 | ||||
-rw-r--r-- | drumgizmo/output/wavfile.cc | 35 | ||||
-rw-r--r-- | drumgizmo/output/wavfile.h | 14 | ||||
-rw-r--r-- | src/audiooutputengine.h | 45 |
8 files changed, 125 insertions, 33 deletions
diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 6433d9d..4f3123b 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -383,6 +383,7 @@ int main(int argc, char* argv[]) } gizmo.setSamplerate(oe->getSamplerate()); + oe->onLatencyChange(gizmo.getLatency()); if(!gizmo.init()) { diff --git a/drumgizmo/jackclient.cc b/drumgizmo/jackclient.cc index e493e1b..fb71b1b 100644 --- a/drumgizmo/jackclient.cc +++ b/drumgizmo/jackclient.cc @@ -57,6 +57,12 @@ int JackClient::wrapJackProcess(jack_nframes_t nframes, void* arg) return static_cast<JackClient*>(arg)->process(nframes); } +void JackClient::latencyCallback(jack_latency_callback_mode_t mode, + void* arg) +{ + static_cast<JackClient*>(arg)->jackLatencyCallback(mode); +} + JackClient::JackClient() : client{nullptr} , processes{} @@ -65,6 +71,12 @@ JackClient::JackClient() jack_status_t status; client = jack_client_open("DrumGizmo", JackNullOption, &status); jack_set_process_callback(client, JackClient::wrapJackProcess, this); + + // Register callback which is called by jack when it wants to know about the + // current port latency. + jack_set_latency_callback(client, + JackClient::latencyCallback, + this); } JackClient::~JackClient() @@ -103,6 +115,14 @@ int JackClient::process(jack_nframes_t num_frames) return 0; } +void JackClient::jackLatencyCallback(jack_latency_callback_mode_t mode) +{ + for(auto& ptr : processes) + { + ptr->jackLatencyCallback(mode); + } +} + std::size_t JackClient::getBufferSize() const { return jack_get_buffer_size(client); diff --git a/drumgizmo/jackclient.h b/drumgizmo/jackclient.h index 82cc0ed..83e5339 100644 --- a/drumgizmo/jackclient.h +++ b/drumgizmo/jackclient.h @@ -40,6 +40,7 @@ class JackProcess public: virtual ~JackProcess(); virtual void process(jack_nframes_t num_frames) = 0; + virtual void jackLatencyCallback(jack_latency_callback_mode_t mode) {} }; // -------------------------------------------------------------------- @@ -78,6 +79,8 @@ private: bool is_active; int process(jack_nframes_t num_frames); + void jackLatencyCallback(jack_latency_callback_mode_t mode); static int wrapJackProcess(jack_nframes_t nframes, void* arg); + static void latencyCallback(jack_latency_callback_mode_t mode, void* arg); }; diff --git a/drumgizmo/output/jackaudio.cc b/drumgizmo/output/jackaudio.cc index abd7d4f..75766d1 100644 --- a/drumgizmo/output/jackaudio.cc +++ b/drumgizmo/output/jackaudio.cc @@ -33,6 +33,7 @@ JackAudioOutputEngine::JackAudioOutputEngine(JackClient& client) : AudioOutputEngine{} , client(client) , channels{} + , latency{0} { client.add(*this); } @@ -122,6 +123,11 @@ size_t JackAudioOutputEngine::getSamplerate() const return client.getSampleRate(); } +void JackAudioOutputEngine::onLatencyChange(std::size_t latency) +{ + this->latency = latency; +} + JackAudioOutputEngine::Channel::Channel(JackClient& client, const std::string& name, std::size_t buffer_size) @@ -130,3 +136,33 @@ JackAudioOutputEngine::Channel::Channel(JackClient& client, { samples.resize(buffer_size); } + +void JackAudioOutputEngine::jackLatencyCallback(jack_latency_callback_mode_t mode) +{ + jack_latency_range_t range; + switch(mode) + { + case JackCaptureLatency: + // We do not have any audio input ports. Use this for when we do... +// jack_port_get_latency_range(port_feeding_input_port, +// JackPlaybackLatency, +// &range); +// range.min += 0; +// range.max += 0; +// jack_port_set_latency_range(input_port, JackPlaybackLatency, &range); + break; + case JackPlaybackLatency: + for(auto& channel : channels) + { + jack_port_get_latency_range(channel.port.port, + JackPlaybackLatency, + &range); + range.min += latency; + range.max += latency; + jack_port_set_latency_range(channel.port.port, + JackPlaybackLatency, + &range); + } + break; + } +} diff --git a/drumgizmo/output/jackaudio.h b/drumgizmo/output/jackaudio.h index 324e95a..b8fbcab 100644 --- a/drumgizmo/output/jackaudio.h +++ b/drumgizmo/output/jackaudio.h @@ -49,11 +49,14 @@ public: void post(size_t nsamples) override; size_t getBufferSize() const override; size_t getSamplerate() const override; + void onLatencyChange(std::size_t latency) override; // based on JackProcess void process(jack_nframes_t num_frames) override; + void jackLatencyCallback(jack_latency_callback_mode_t mode) override; private: + struct Channel { JackPort port; @@ -66,4 +69,5 @@ private: JackClient& client; std::vector<Channel> channels; Semaphore sema; + std::size_t latency{0}; }; diff --git a/drumgizmo/output/wavfile.cc b/drumgizmo/output/wavfile.cc index a9d8b0b..20b63bd 100644 --- a/drumgizmo/output/wavfile.cc +++ b/drumgizmo/output/wavfile.cc @@ -33,6 +33,7 @@ WavfileOutputEngine::WavfileOutputEngine() , info{} , channels{} , file{"output"} + , latency{0} { info.samplerate = 44100; info.channels = 1; @@ -69,7 +70,8 @@ bool WavfileOutputEngine::init(const Channels& data) return true; } -void WavfileOutputEngine::setParm(const std::string& parm, const std::string& value) +void WavfileOutputEngine::setParm(const std::string& parm, + const std::string& value) { if(parm == "file") { @@ -105,11 +107,11 @@ void WavfileOutputEngine::stop() { } -void WavfileOutputEngine::pre(size_t nsamples) +void WavfileOutputEngine::pre(std::size_t nsamples) { } -void WavfileOutputEngine::run(int ch, sample_t* samples, size_t nsamples) +void WavfileOutputEngine::run(int ch, sample_t* samples, std::size_t nsamples) { if(static_cast<unsigned int>(ch) >= channels.size()) { @@ -118,14 +120,35 @@ void WavfileOutputEngine::run(int ch, sample_t* samples, size_t nsamples) return; } - sf_writef_float(channels[ch], samples, nsamples); + // Skip the initial 'latency' samples. + if(nsamples <= latency) + { + return; + } + + nsamples -= latency; + + sf_writef_float(channels[ch], samples + latency, nsamples); } -void WavfileOutputEngine::post(size_t nsamples) +void WavfileOutputEngine::post(std::size_t nsamples) { + if(latency > nsamples) + { + latency -= nsamples; + } + else + { + latency = 0; + } } -size_t WavfileOutputEngine::getSamplerate() const +std::size_t WavfileOutputEngine::getSamplerate() const { return info.samplerate; } + +void WavfileOutputEngine::onLatencyChange(std::size_t latency) +{ + this->latency = latency; +} diff --git a/drumgizmo/output/wavfile.h b/drumgizmo/output/wavfile.h index dfe422c..656c0cd 100644 --- a/drumgizmo/output/wavfile.h +++ b/drumgizmo/output/wavfile.h @@ -25,6 +25,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #pragma once + +#include <cstddef> #include <string> #include <vector> @@ -44,15 +46,17 @@ public: void setParm(const std::string& parm, const std::string& value) override; bool start() override; void stop() override; - void pre(size_t nsamples) override; - void run(int ch, sample_t* samples, size_t nsamples) override; - void post(size_t nsamples) override; - size_t getSamplerate() const override; + void pre(std::size_t nsamples) override; + void run(int ch, sample_t* samples, std::size_t nsamples) override; + void post(std::size_t nsamples) override; + std::size_t getSamplerate() const override; + void onLatencyChange(std::size_t latency) override; private: SF_INFO info; std::vector<SNDFILE*> channels; - size_t num_channels; + std::size_t num_channels; std::string file; + std::size_t latency; }; diff --git a/src/audiooutputengine.h b/src/audiooutputengine.h index df8b0ee..338b5cd 100644 --- a/src/audiooutputengine.h +++ b/src/audiooutputengine.h @@ -24,39 +24,40 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_AUDIOOUTPUTENGINE_H__ -#define __DRUMGIZMO_AUDIOOUTPUTENGINE_H__ +#pragma once +#include <cstddef> #include <string> -#include <stdlib.h> + #include <audiotypes.h> #include "channel.h" -class AudioOutputEngine { +class AudioOutputEngine +{ public: - virtual ~AudioOutputEngine() {} + virtual ~AudioOutputEngine() = default; - virtual bool init(const Channels& channels) = 0; + virtual bool init(const Channels& channels) = 0; - virtual void setParm(const std::string& parm, const std::string& value) = 0; + virtual void setParm(const std::string& parm, const std::string& value) = 0; - virtual bool start() = 0; - virtual void stop() = 0; + virtual bool start() = 0; + virtual void stop() = 0; - virtual void pre(size_t nsamples) = 0; - virtual void run(int ch, sample_t *samples, size_t nsamples) = 0; - virtual void post(size_t nsamples) = 0; + virtual void pre(std::size_t nsamples) = 0; + virtual void run(int ch, sample_t *samples, std::size_t nsamples) = 0; + virtual void post(std::size_t nsamples) = 0; - // Reimplement this if you wish to use internal buffer directly. - virtual sample_t *getBuffer(int ch) const { return NULL; } + //! Overload this method to use internal buffer directly. + virtual sample_t *getBuffer(int ch) const { return NULL; } - /* - * Overload this method to force engine to use different buffer size. - */ - virtual size_t getBufferSize() const { return 1024; } - - virtual size_t getSamplerate() const { return 44100; } -}; + //! Overload this method to force engine to use different buffer size. + virtual std::size_t getBufferSize() const { return 1024; } -#endif/*__DRUMGIZMO_AUDIOOUTPUTENGINE_H__*/ + virtual std::size_t getSamplerate() const { return 44100; } + + //! Overload this method to get notification of latency changes. + //! \param latency The new latency in samples. + virtual void onLatencyChange(std::size_t latency) {} +}; |