diff options
Diffstat (limited to 'drumgizmo')
| -rw-r--r-- | drumgizmo/Makefile.am | 5 | ||||
| -rw-r--r-- | drumgizmo/enginefactory.cc | 12 | ||||
| -rw-r--r-- | drumgizmo/enginefactory.h | 5 | ||||
| -rw-r--r-- | drumgizmo/input/jackmidi.cc | 145 | ||||
| -rw-r--r-- | drumgizmo/input/jackmidi.h | 67 | ||||
| -rw-r--r-- | drumgizmo/input/midifile.cc | 4 | ||||
| -rw-r--r-- | drumgizmo/input/midifile.h | 6 | ||||
| -rw-r--r-- | drumgizmo/jackclient.cc | 22 | ||||
| -rw-r--r-- | drumgizmo/jackclient.h | 22 | ||||
| -rw-r--r-- | drumgizmo/output/jackaudio.cc | 35 | ||||
| -rw-r--r-- | drumgizmo/output/jackaudio.h | 15 | 
11 files changed, 289 insertions, 49 deletions
| diff --git a/drumgizmo/Makefile.am b/drumgizmo/Makefile.am index 4eb770c..4c34f6c 100644 --- a/drumgizmo/Makefile.am +++ b/drumgizmo/Makefile.am @@ -41,6 +41,11 @@ drumgizmo_SOURCES += input/midifile.cc  drumgizmo_CXXFLAGS += -DHAVE_INPUT_MIDIFILE  endif # HAVE_INPUT_MIDIFILE +if HAVE_INPUT_JACKMIDI +drumgizmo_SOURCES += input/jackmidi.cc +drumgizmo_CXXFLAGS += -DHAVE_INPUT_JACKMIDI +endif # HAVE_INPUT_JACKMIDI +  if HAVE_OUTPUT_DUMMY  drumgizmo_SOURCES += output/outputdummy.cc  drumgizmo_CXXFLAGS += -DHAVE_OUTPUT_DUMMY diff --git a/drumgizmo/enginefactory.cc b/drumgizmo/enginefactory.cc index cb332ed..06f8141 100644 --- a/drumgizmo/enginefactory.cc +++ b/drumgizmo/enginefactory.cc @@ -26,6 +26,7 @@   */  #include <iostream> +#include "cpp11fix.h" // required for c++11  #include "enginefactory.h"  EngineFactory::EngineFactory() @@ -42,6 +43,9 @@ EngineFactory::EngineFactory()  #ifdef HAVE_INPUT_MIDIFILE  	input.push_back("midifile");  #endif +#ifdef HAVE_INPUT_JACKMIDI +	input.push_back("jackmidi"); +#endif  	// list available output engines  #ifdef HAVE_OUTPUT_DUMMY @@ -85,6 +89,12 @@ std::unique_ptr<AudioInputEngine> EngineFactory::createInput(std::string const &  		return std::make_unique<MidifileInputEngine>();  	}  #endif +#ifdef HAVE_INPUT_JACKMIDI +	if (name == "jackmidi") { +		prepareJack(); +		return std::make_unique<JackMidiInputEngine>(*jack); +	} +#endif  	// todo: add more engines @@ -111,7 +121,7 @@ std::unique_ptr<AudioOutputEngine> EngineFactory::createOutput(std::string const  #ifdef HAVE_OUTPUT_JACKAUDIO  	if (name == "jackaudio") {  		prepareJack(); -		return std::make_unique<JackaudioOutputEngine>(*jack); +		return std::make_unique<JackAudioOutputEngine>(*jack);  	}  #endif diff --git a/drumgizmo/enginefactory.h b/drumgizmo/enginefactory.h index 6457ed1..f00df99 100644 --- a/drumgizmo/enginefactory.h +++ b/drumgizmo/enginefactory.h @@ -28,7 +28,6 @@  #include <list>  #include <string>  #include <memory> -#include "cpp11fix.h" // required for c++11  #include "audioinputengine.h"  #include "audiooutputengine.h" @@ -46,6 +45,10 @@  	#include "input/midifile.h"  #endif +#ifdef HAVE_INPUT_JACKMIDI +	#include "input/jackmidi.h" +#endif +  #ifdef HAVE_OUTPUT_DUMMY  	#include "output/outputdummy.h"  #endif diff --git a/drumgizmo/input/jackmidi.cc b/drumgizmo/input/jackmidi.cc new file mode 100644 index 0000000..2d399c2 --- /dev/null +++ b/drumgizmo/input/jackmidi.cc @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            jackmidi.cc + * + *  Mo 25. Jan 11:26:06 CET 2016 + *  Copyright 2016 Christian Glöckner + *  cgloeckner@freenet.de + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo 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. + * + *  DrumGizmo 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 DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <iostream> +#include <cassert> + +#include "cpp11fix.h" // required for c++11 +#include "jackmidi.h" + +int const NOTE_ON = 0x90; + +JackMidiInputEngine::JackMidiInputEngine(JackClient& client) +	: AudioInputEngine{} +	, JackProcess{} +	, client{client} +	, port{nullptr} +	, midimap{} +	, midi_mapper{} +	, list{nullptr} +	, pos{0u} { +	client.add(*this); +} + +JackMidiInputEngine::~JackMidiInputEngine() { +	client.remove(*this); +} + +bool JackMidiInputEngine::isMidiEngine() { +	return true; +} + +bool JackMidiInputEngine::init(Instruments& instruments) { +	if (midimap == "") { +		std::cerr << "[JackMidiInputEngine] Missing midimap filename\n"; +		return false; +	} +	MidiMapParser p{midimap}; +	if (p.parse()) { +		std::cerr << "[JackmidiInputEngine] Failed to parse midimap '" +			<< midimap << "'\n"; +		return false; +	} +	midi_mapper.midimap = p.midimap; +	for (auto i = 0u; i < instruments.size(); ++i) { +		auto name = instruments[i]->name(); +		midi_mapper.instrmap[name] = i; +	} +	port = std::make_unique<JackPort>(client, "drumgizmo_midiin", +		JACK_DEFAULT_MIDI_TYPE, JackPortIsInput); +	return true; +} + +void JackMidiInputEngine::setParm(std::string parm, std::string value) { +	if (parm == "midimap") { +		// apply midimap filename +		midimap = value; +		 +	} else { +		std::cerr << "[JackMidiInputEngine] Unsupported parameter '" +			<< parm << "'\n"; +	} +} + +bool JackMidiInputEngine::start() { +	client.activate(); +	return true; +} + +void JackMidiInputEngine::stop() { +} + +void JackMidiInputEngine::pre() { +} + +event_t* JackMidiInputEngine::run(size_t pos, size_t len, size_t* nevents) { +	*nevents = listsize; +	event_t* l = list; +	printf("Owning raw pointer at drumgizmo/input/jackmidiinput.cc - GET RID OF THEM!\n"); +	list = (event_t *)malloc(sizeof(event_t) * 1000); +	listsize = 0; +	return l; +} + +void JackMidiInputEngine::post() { +} + +void JackMidiInputEngine::process(jack_nframes_t num_frames) { +	assert(port != nullptr); +	void* buffer = port->getBuffer(num_frames); +	jack_nframes_t num_events = jack_midi_get_event_count(buffer); + +	for(jack_nframes_t i = 0; i < num_events; ++i) { +		jack_midi_event_t event; +		jack_midi_event_get(&event, buffer, i); +		if(event.size != 3) { +			continue; +		} +		if((event.buffer[0] & NOTE_ON) != NOTE_ON) { +			continue; +		} +		int key = event.buffer[1]; +		int velocity = event.buffer[2]; +		printf("Event key:%d vel:%d\n", key, velocity); +		int k = midi_mapper.lookup(key); +		if(k != -1 && velocity) { +			list[listsize].type = TYPE_ONSET; +			list[listsize].instrument = k; +			list[listsize].velocity = velocity / 127.0; +			list[listsize].offset = event.time; +			++listsize; +		} +	} +	jack_midi_clear_buffer(buffer); +	pos += num_frames; +} + +/* +		DrumKit* kit; +		size_t pos; +		EventQueue *eventqueue; +*/ + diff --git a/drumgizmo/input/jackmidi.h b/drumgizmo/input/jackmidi.h new file mode 100644 index 0000000..3c64f2d --- /dev/null +++ b/drumgizmo/input/jackmidi.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            jackmidi.h + * + *  Mo 25. Jan 11:26:06 CET 2016 + *  Copyright 2016 Christian Glöckner + *  cgloeckner@freenet.de + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo 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. + * + *  DrumGizmo 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 DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#pragma once +#include <memory> +#include <jack/jack.h> +#include <jack/midiport.h> + +#include "audioinputengine.h" +#include "midimapper.h" +#include "midimapparser.h" +#include "../jackclient.h" + +class JackMidiInputEngine +	: public AudioInputEngine +	, public JackProcess { +	public: +		JackMidiInputEngine(JackClient& client); +		~JackMidiInputEngine(); +		 +		// based on AudioInputEngine +		bool isMidiEngine() override; +		bool init(Instruments& instruments) override; +		void setParm(std::string parm, std::string value) override; +		bool start() override; +		void stop() override; +		void pre() override; +		event_t* run(size_t pos, size_t len, size_t* nevents) override; +		void post() override; +		 +		// based on JackProcess +		void process(jack_nframes_t num_frames) override; +		 +	private: +		JackClient& client; +		std::unique_ptr<JackPort> port; +		 +		std::string midimap; +		MidiMapper midi_mapper; +		std::size_t pos; +		 +		event_t* list; +		size_t listsize; +}; diff --git a/drumgizmo/input/midifile.cc b/drumgizmo/input/midifile.cc index 323a198..c9aeaf8 100644 --- a/drumgizmo/input/midifile.cc +++ b/drumgizmo/input/midifile.cc @@ -137,7 +137,7 @@ event_t* MidifileInputEngine::run(size_t pos, size_t len, size_t *nevents) {  				current_event->midi_buffer[2] > 0) {  				if(evs == nullptr) { -					printf("Yet another raw owning pointer was generated by drumgizmo/input/midifile.cc - GET RID OF THEM!\n"); +					printf("Owning raw pointer at drumgizmo/input/midifile.cc - GET RID OF THEM!\n");  					evs = (event_t *)malloc(sizeof(event_t) * 1000);  				} @@ -171,7 +171,7 @@ event_t* MidifileInputEngine::run(size_t pos, size_t len, size_t *nevents) {  			offset += current_max_time;  		} else {  			if(evs == nullptr) { -				printf("Yet another raw owning pointer was generated by drumgizmo/input/midifile.cc - GET RID OF THEM!\n"); +				printf("Owning raw pointer at drumgizmo/input/midifile.cc - GET RID OF THEM!\n");  				evs = (event_t *)malloc(sizeof(event_t) * 1000);  			}  			evs[num_events].type = TYPE_STOP; diff --git a/drumgizmo/input/midifile.h b/drumgizmo/input/midifile.h index 85abfc9..6749339 100644 --- a/drumgizmo/input/midifile.h +++ b/drumgizmo/input/midifile.h @@ -30,9 +30,9 @@  #include <event.h>  #include <smf.h> -#include <audioinputengine.h> -#include <midimapper.h> -#include <midimapparser.h> +#include "audioinputengine.h" +#include "midimapper.h" +#include "midimapparser.h"  class MidifileInputEngine  	: public AudioInputEngine { diff --git a/drumgizmo/jackclient.cc b/drumgizmo/jackclient.cc index 8d422cb..376f3fb 100644 --- a/drumgizmo/jackclient.cc +++ b/drumgizmo/jackclient.cc @@ -33,29 +33,23 @@ JackProcess::~JackProcess() {  // -------------------------------------------------------------------- -JackChannel::JackChannel() -	: samples{} -	, client{nullptr} -	, port{nullptr} { -} - -JackChannel::JackChannel(JackClient& client, std::size_t buffer_size, -	std::string const & name) -	: samples{} -	, client{client.client} +JackPort::JackPort(JackClient& client, std::string const & name, const char * type, JackPortFlags flags) +	: client{client.client}  	// register jack port for given client -	, port{jack_port_register(this->client, name.c_str(), -		JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)} { -	samples.resize(buffer_size); +	, port{jack_port_register(this->client, name.c_str(), type, flags, 0)} {  } -JackChannel::~JackChannel() { +JackPort::~JackPort() {  	if (port != nullptr) {  		assert(client != nullptr);  		jack_port_unregister(client, port);  	}  } +void* JackPort::getBuffer(jack_nframes_t num_frames) { +	return jack_port_get_buffer(port, num_frames); +} +  // --------------------------------------------------------------------  int _wrap_jack_process(jack_nframes_t nframes, void* arg){ diff --git a/drumgizmo/jackclient.h b/drumgizmo/jackclient.h index ef7abf1..2574f18 100644 --- a/drumgizmo/jackclient.h +++ b/drumgizmo/jackclient.h @@ -43,21 +43,23 @@ class JackProcess {  // -------------------------------------------------------------------- -struct JackChannel { -	std::vector<sample_t> samples; -	jack_client_t* const client; -	jack_port_t* const port; -	 -	JackChannel(); -	JackChannel(JackClient& client, std::size_t buffer_size, -		std::string const & name); -	~JackChannel(); +// RAII-wrapper for jack_port_t +class JackPort { +	public: +		JackPort(JackClient& client, std::string const & name, const char * type, JackPortFlags flags); +		~JackPort(); +		 +		void* getBuffer(jack_nframes_t num_frames); +		 +	private: +		jack_client_t* const client; +		jack_port_t* const port;  };  // --------------------------------------------------------------------  class JackClient { -	friend struct JackChannel; +	friend struct JackPort;  	public:  		JackClient(); diff --git a/drumgizmo/output/jackaudio.cc b/drumgizmo/output/jackaudio.cc index 07ae4b5..634b7d1 100644 --- a/drumgizmo/output/jackaudio.cc +++ b/drumgizmo/output/jackaudio.cc @@ -29,17 +29,18 @@  #include "jackaudio.h" -JackaudioOutputEngine::JackaudioOutputEngine(JackClient& client) +JackAudioOutputEngine::JackAudioOutputEngine(JackClient& client)  	: client(client) // wanna use initializer braces here but jenkins fails  	, channels{}  	, sema{"jackaudio"} {  	client.add(*this);  } -JackaudioOutputEngine::~JackaudioOutputEngine() { +JackAudioOutputEngine::~JackAudioOutputEngine() { +	client.remove(*this);  } -bool JackaudioOutputEngine::init(Channels data) { +bool JackAudioOutputEngine::init(Channels data) {  	channels.clear();  	channels.reserve(data.size());  	auto i = 0u; @@ -48,10 +49,10 @@ bool JackaudioOutputEngine::init(Channels data) {  	for (auto const & elem: data) {  		auto name = std::to_string(i) + "-" + elem.name;  		// initialize new channel -		channels.emplace_back(client, buffer_size, name); +		channels.emplace_back(client, name, buffer_size);  		if (channels.back().port == nullptr) { -			std::cerr << "[JackaudioOutputEngine] Cannot create jack " +			std::cerr << "[JackAudioOutputEngine] Cannot create jack "  				<< "port for channel #" << i << "\n";  			return false;  		} @@ -60,31 +61,31 @@ bool JackaudioOutputEngine::init(Channels data) {  	return true;  } -void JackaudioOutputEngine::setParm(std::string parm, std::string value) { +void JackAudioOutputEngine::setParm(std::string parm, std::string value) {  } -bool JackaudioOutputEngine::start() { +bool JackAudioOutputEngine::start() {  	client.activate();  	return true;  } -void JackaudioOutputEngine::stop() { +void JackAudioOutputEngine::stop() {  } -void JackaudioOutputEngine::pre(size_t nsamples) { +void JackAudioOutputEngine::pre(size_t nsamples) {  } -void JackaudioOutputEngine::run(int ch, sample_t* samples, size_t nsamples) { +void JackAudioOutputEngine::run(int ch, sample_t* samples, size_t nsamples) {  	for (auto i = 0u; i < nsamples; ++i) {  		channels[ch].samples[i] = samples[i];  	}  } -void JackaudioOutputEngine::post(size_t nsamples) { +void JackAudioOutputEngine::post(size_t nsamples) {  	sema.wait();  } -void JackaudioOutputEngine::process(jack_nframes_t num_frames) { +void JackAudioOutputEngine::process(jack_nframes_t num_frames) {  	assert(num_frames == getBufferSize());  	for (auto& channel: channels) { @@ -97,10 +98,16 @@ void JackaudioOutputEngine::process(jack_nframes_t num_frames) {  	sema.post();  } -size_t JackaudioOutputEngine::getBufferSize() { +size_t JackAudioOutputEngine::getBufferSize() {  	return client.getBufferSize();  } -size_t JackaudioOutputEngine::samplerate() { +size_t JackAudioOutputEngine::samplerate() {  	return client.getSampleRate();  } + +JackAudioOutputEngine::Channel::Channel(JackClient& client, std::string const & name, std::size_t buffer_size) +	: port{client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0} +	, samples{} { +	samples.resize(buffer_size); +} diff --git a/drumgizmo/output/jackaudio.h b/drumgizmo/output/jackaudio.h index 13ed75f..12539c5 100644 --- a/drumgizmo/output/jackaudio.h +++ b/drumgizmo/output/jackaudio.h @@ -31,12 +31,12 @@  #include "audiooutputengine.h"  #include "../jackclient.h" -class JackaudioOutputEngine +class JackAudioOutputEngine  	: public AudioOutputEngine  	, public JackProcess {  	public: -		JackaudioOutputEngine(JackClient& client); -		~JackaudioOutputEngine(); +		JackAudioOutputEngine(JackClient& client); +		~JackAudioOutputEngine();  		// based on AudioOutputEngine  		bool init(Channels chan) override; @@ -53,7 +53,14 @@ class JackaudioOutputEngine  		void process(jack_nframes_t num_frames) override;  	private: +		struct Channel { +			JackPort port; +			std::vector<sample_t> samples; +			 +			Channel(JackClient& client, std::string const & name, std::size_t buffer_size); +		}; +		  		JackClient& client; -		std::vector<JackChannel> channels; +		std::vector<Channel> channels;  		Semaphore sema;  }; | 
