Ecasound and timebase master
Julien Claassen <[email protected]> Wed, 17 Jul 2013 20:50:37 +0200 (CEST)
| Newsgroups | gmane.comp.audio.ecasound.general |
|---|---|
| Message-ID | <[email protected]> |
Hello Kai!
I wondered, if it would be possible for Ecasound to become a timebase
master. So, taht it can give JACK hints about beats and bars. I took a look at
klick, the metronome by Florian Schmidt, if I'm not mistaken. I think I found
the relevant parts in metronome_jack.cc, which you find attached. the
process_callback looks rather promising.
My question: would it be possible to easily add this functionality to
Ecasound, sayas a built-in object? Perhaps as in input object (like null) or
as a modifier (effect) or perhaps as a general feature. As an effect it ouwld
be most valuable, since it might be possible to use other controllers on it.
Though I dare say, that as an effect it can't produce its own click sound.
The reason I am not really comfortable with using klick itself is this: in
its interactive mode, it can't be used as a timebase master and if its not in
interactive mode, it can't be adjusted on the fly. It would have to be killed
and restarted, which is awkward. Besides Ecasound is the most feasable
transport master after all, it being the DAW in the system.
The plan is this: have a software, that can generate JACK transport timebase
(or whatever it's officially called) and use jack_midi_clock to generate
start/stop and clock events from it, to sync it to Midish. I know, that
implementing more MIDI capabilities in Ecasound would take a huge effort and
is out fo the question for the time being. But I thought, that this might fit
in with the current structure and klick looked reasonable small, so it would
be easy to pinch the code. I'd be prepared to do some work on it, on my own,
but I will need guidance. Before I can do anything though, I certainly need
your insides on where to best put it, if it is at all possible.
I'll keep on looking at klick to see, if I can spot more helpful code and
piece the really important bits together. Probably the good thing about it all
is, that it is already written in c++.
Warm regards
Julien
----------------------------------------
http://juliencoder.de/nama/music.html
------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
Ecasound-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ecasound-list
metronome_jack.cc
(text/x-c++src, 2.7 KB)
/* * klick - an advanced metronome for jack * * Copyright (C) 2007-2009 Dominic Sacré <[email protected]> * * 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. */ #include "metronome_jack.hh" #include "audio_interface_jack.hh" #include "audio_chunk.hh" #include <jack/jack.h> #include <jack/transport.h> #include "util/debug.hh" MetronomeJack::MetronomeJack(AudioInterfaceJack & audio) : Metronome(audio) , _audio(audio) , _last_click_frame(0) { } MetronomeJack::~MetronomeJack() { } void MetronomeJack::process_callback(sample_t * /*buffer*/, nframes_t nframes) { if (!active() || !_audio.transport_rolling()) { return; } jack_position_t pos = _audio.position(); if (!(pos.valid & JackPositionBBT)) { // not much we can do return; } // make sure the transport master provided us with sane position info ASSERT(pos.beats_per_minute > 0.0); ASSERT(pos.beats_per_bar > 0.0); ASSERT(pos.ticks_per_beat > 0.0); ASSERT(pos.beat > 0 && pos.beat <= pos.beats_per_bar); ASSERT(pos.tick >= 0 && pos.tick < pos.ticks_per_beat); // convert BBT position to a frame number in this period double frames_per_beat = _audio.samplerate() * 60.0 / pos.beats_per_minute; nframes_t offset = (nframes_t)(frames_per_beat * (1.0 - (pos.tick / pos.ticks_per_beat))); bool emphasis; // avoid playing the same click twice due to rounding errors if (_last_click_frame && (pos.frame >= _last_click_frame) && (pos.frame < _last_click_frame + MIN_FRAMES_DIFF)) { return; } if (offset % (nframes_t)frames_per_beat == 0) { // click starts at first frame. pos already refers to this beat offset = 0; emphasis = (pos.beat == 1); // deal with faulty timebase masters if ((pos.beat == pos.beats_per_bar + 1) || (pos.beat == pos.beats_per_bar && pos.tick == pos.ticks_per_beat)) { emphasis = true; } _last_click_frame = pos.frame; } else if (offset < nframes) { // click starts somewhere during this period. since pos is the position at the start // of the period, the click played is actually at "pos + 1" emphasis = (pos.beat == (int)pos.beats_per_bar); _last_click_frame = pos.frame + offset; } else { // no click in this period return; } play_click(emphasis, offset); }