From 242285d4863a66b4033ca7b5371bae5160ccf62c Mon Sep 17 00:00:00 2001 From: deva Date: Mon, 21 Jul 2008 11:01:04 +0000 Subject: First very simple sample implementation. Basic MIDI test framework. --- src/Makefile.am | 12 ++++--- src/drumgizmo.cc | 54 ++++++++++++++++++++++++++++- src/event.cc | 43 +++++++++++++++++++++++ src/event.h | 47 +++++++++++++++++++++++++ src/jackclient.cc | 102 +++++++++++++++++++++++++++++++++++++++--------------- src/jackclient.h | 14 ++++++-- src/sample.cc | 55 +++++++++++++++++++++++++++++ src/sample.h | 41 ++++++++++++++++++++++ 8 files changed, 333 insertions(+), 35 deletions(-) create mode 100644 src/event.cc create mode 100644 src/event.h create mode 100644 src/sample.cc create mode 100644 src/sample.h diff --git a/src/Makefile.am b/src/Makefile.am index aec9534..7e7ebbe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,12 +1,16 @@ bin_PROGRAMS = drumgizmo -drumgizmo_LDADD = $(JACK_LIBS) +drumgizmo_LDADD = $(JACK_LIBS) $(SNDFILE_LIBS) -drumgizmo_CXXFLAGS = $(JACK_CXXFLAGS) +drumgizmo_CXXFLAGS = $(JACK_CXXFLAGS) $(SNDFILE_CXXFLAGS) drumgizmo_SOURCES = \ drumgizmo.cc \ - jackclient.cc + event.cc \ + jackclient.cc \ + sample.cc EXTRA_DIST = \ - jackclient.h + jackclient.h \ + event.h \ + sample.h diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 019abbb..737a197 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -24,14 +24,66 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ - #include "jackclient.h" +#include +#include + +static jack_port_t *test_midi_port = NULL; +static size_t timer = 0; + +int process(jack_nframes_t nframes, void *arg) +{ + // if(jack_port_connected_to(test_midi_port, "DrumGizmo:midi_in")) { + void* port_buf = jack_port_get_buffer(test_midi_port, nframes); + + if(timer > 44100) { // activate every second (44100 samples) + printf("ding\n"); + + jack_nframes_t time = 1; + size_t size = 3; + jack_midi_data_t all_notes_off[] = { 0xB0, 123, 0 }; + jack_midi_event_write(port_buf, time, all_notes_off, size); + timer = 0; + } + + timer += nframes; + + return 0; +} + +void sendMidi() +{ + jack_status_t status; + + jack_client_t *jack_client = jack_client_open("MidiTest", JackNullOption, &status); + + test_midi_port = jack_port_register(jack_client, + "midi_out", + JACK_DEFAULT_MIDI_TYPE, + JackPortIsOutput,// | JackPortIsTerminal, + 0); + + jack_set_process_callback(jack_client, process, NULL); + + jack_activate(jack_client); + + jack_connect(jack_client, "MidiTest:midi_out", "DrumGizmo:midi_in"); + + jack_connect(jack_client, "DrumGizmo:output_1", "system:playback_1"); + jack_connect(jack_client, "DrumGizmo:output_2", "system:playback_2"); +} + int main(int argc, char *argv[]) { JackClient client; client.activate(); + + sendMidi(); + + while(1) sleep(1); + return 0; } diff --git a/src/event.cc b/src/event.cc new file mode 100644 index 0000000..804d42f --- /dev/null +++ b/src/event.cc @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * event.cc + * + * Mon Jul 21 10:56:02 CEST 2008 + * Copyright 2008 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * 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 "event.h" + +Event::Event(Sample *sample, size_t onset) +{ + this->sample = sample; + this->onset = onset; + duration = 0; +} + +Event::~Event() +{ +} + +bool Event::operator<(const Event& event) const +{ + return onset + duration < event.onset + event.duration; +} diff --git a/src/event.h b/src/event.h new file mode 100644 index 0000000..4f277a7 --- /dev/null +++ b/src/event.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * event.h + * + * Mon Jul 21 10:56:01 CEST 2008 + * Copyright 2008 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * 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. + */ +#ifndef __DRUMGIZMO_EVENT_H__ +#define __DRUMGIZMO_EVENT_H__ + +#include +#include "sample.h" + +class Event { +public: + Event(Sample *sample, size_t onset); + ~Event(); + + bool operator<(const Event& event) const; + + Sample *sample; + size_t duration; + size_t onset; +}; + +typedef std::set< Event > Events; + +#endif/*__DRUMGIZMO_EVENT_H__*/ diff --git a/src/jackclient.cc b/src/jackclient.cc index af25da0..42a85c2 100644 --- a/src/jackclient.cc +++ b/src/jackclient.cc @@ -56,7 +56,7 @@ JackClient::JackClient(size_t num_inputs, size_t num_outputs) // Setup input port midi_port = jack_port_register(jack_client, - "Midi in", + "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput,// | JackPortIsTerminal, 0); @@ -64,7 +64,7 @@ JackClient::JackClient(size_t num_inputs, size_t num_outputs) // Setup input ports for(size_t i = 0; i < num_inputs; i++) { char port_name[32]; - sprintf(port_name, "Port %i", i); + sprintf(port_name, "input_%i", i + 1); jack_port_t *port = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, @@ -76,7 +76,7 @@ JackClient::JackClient(size_t num_inputs, size_t num_outputs) // Setup output ports for(size_t i = 0; i < num_outputs; i++) { char port_name[32]; - sprintf(port_name, "Port %i", i); + sprintf(port_name, "output_%i", i + 1); jack_port_t *port = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, @@ -85,15 +85,18 @@ JackClient::JackClient(size_t num_inputs, size_t num_outputs) output_ports.push_back(port); } - jack_on_shutdown(jack_client, _wrap_jack_shutdown, this); + //jack_on_shutdown(jack_client, _wrap_jack_shutdown, this); jack_set_process_callback(jack_client, _wrap_jack_process, this); - jack_set_thread_init_callback(jack_client, _wrap_jack_thread_init, this); - jack_set_freewheel_callback(jack_client, _wrap_jack_freewheel_mode, this); - jack_set_buffer_size_callback(jack_client, _wrap_jack_buffer_size, this); - jack_set_sample_rate_callback(jack_client, _wrap_jack_sample_rate, this); - jack_set_port_registration_callback(jack_client, _wrap_jack_port_registration, this); - jack_set_graph_order_callback(jack_client, _wrap_jack_graph_order, this); - jack_set_xrun_callback(jack_client, _wrap_jack_xrun, this); + //jack_set_thread_init_callback(jack_client, _wrap_jack_thread_init, this); + //jack_set_freewheel_callback(jack_client, _wrap_jack_freewheel_mode, this); + //jack_set_buffer_size_callback(jack_client, _wrap_jack_buffer_size, this); + //jack_set_sample_rate_callback(jack_client, _wrap_jack_sample_rate, this); + //jack_set_port_registration_callback(jack_client, _wrap_jack_port_registration, this); + //jack_set_graph_order_callback(jack_client, _wrap_jack_graph_order, this); + //jack_set_xrun_callback(jack_client, _wrap_jack_xrun, this); + + + sample = new Sample("/home/deva/snare.wav"); } JackClient::~JackClient() @@ -112,32 +115,74 @@ void JackClient::shutdown() int JackClient::process(jack_nframes_t nframes) { - /* - int pos = -1; - Params *params = (Params*)arg; - - void *midibuffer = jack_port_get_buffer(params->midi_port, nframes); + void *midibuffer = jack_port_get_buffer(midi_port, nframes); jack_nframes_t midievents = jack_midi_get_event_count(midibuffer); for(jack_nframes_t i = 0; i < midievents; i++) { - jack_midi_event_t event; - jack_midi_event_get(&event, midibuffer, i); - printf("[ Time: %d Size: %d ", event.time, event.size); - for(int j = 0; j < event.size; j++) { - jack_midi_data_t m = event.buffer[j]; + jack_midi_event_t midi_event; + jack_midi_event_get(&midi_event, midibuffer, i); + /* + // Parse midi event + printf("[ Time: %d Size: %d ", midi_event.time, midi_event.size); + for(size_t j = 0; j < midi_event.size; j++) { + jack_midi_data_t m = midi_event.buffer[j]; printf(" Data: %d ", m); } printf("]\n"); - for(int i = 0; i < NUM_PORTS; i++) { - pos = event.time; - } + */ + + // Create trigger event + Event event(sample, midi_event.time); + events.insert(event); + } - for(int i = 0; i < NUM_PORTS; i++) { + jack_midi_clear_buffer(midibuffer); + + // Reset ports + Ports::iterator pi = output_ports.begin(); + while(pi != output_ports.end()) { + + jack_default_audio_sample_t *buffer; + buffer = (jack_default_audio_sample_t *)jack_port_get_buffer(*pi, nframes); + + for(size_t j = 0; j < nframes; j++) { + buffer[j] = 0; + } + + pi++; + } + + // Handle events + Events::iterator ei = events.begin(); + while(ei != events.end()) { + + printf("Event\n"); + + Ports::iterator pi = output_ports.begin(); + while(pi != output_ports.end()) { + + jack_default_audio_sample_t *buffer; + buffer = (jack_default_audio_sample_t *)jack_port_get_buffer(*pi, nframes); + + for(size_t j = 0; j < nframes; j++) { + buffer[j] = sample->data[j];//(float)rand() / (float)RAND_MAX; // Set output + } + + pi++; + } + + ei++; + } + + // Remove all events + events.clear(); + /* + for(size_t i = 0; i < output_ports.size(); i++) { jack_default_audio_sample_t *buffer; - buffer = (jack_default_audio_sample_t *)jack_port_get_buffer(params->drums[i].port, nframes); + buffer = (jack_default_audio_sample_t *)jack_port_get_buffer(output_ports[i], nframes); for(int j = 0; j < nframes; j++) { - if(j == pos) params->drums[i].samples[0].p = -j; - offset_t p = params->drums[i].samples[0].p; + if(j == pos) drums[i].samples[0].p = -j; + offset_t p = drums[i].samples[0].p; size_t data_size = params->drums[i].samples[0].data_size; jack_default_audio_sample_t *samples = params->drums[i].samples[0].data; if(p+j > data_size) buffer[j] = 0; @@ -147,6 +192,7 @@ int JackClient::process(jack_nframes_t nframes) params->drums[i].samples[0].p += nframes; } */ + return 0; } diff --git a/src/jackclient.h b/src/jackclient.h index 02d74e9..cf32eb0 100644 --- a/src/jackclient.h +++ b/src/jackclient.h @@ -32,6 +32,13 @@ #include #include +#include "event.h" +#include "sample.h" + +#define TEST_MIDI + +typedef std::vector< jack_port_t *> Ports; + class JackClient { public: JackClient(size_t num_inputs = 16, size_t num_outputs = 16); @@ -52,9 +59,12 @@ public: private: jack_client_t *jack_client; - std::vector< jack_port_t *> input_ports; - std::vector< jack_port_t *> output_ports; + Ports input_ports; + Ports output_ports; jack_port_t *midi_port; + + Sample *sample; + Events events; }; #endif/*__DRUMGIZMO_JACKCLIENT_H__*/ diff --git a/src/sample.cc b/src/sample.cc new file mode 100644 index 0000000..c375645 --- /dev/null +++ b/src/sample.cc @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * sample.cc + * + * Mon Jul 21 10:23:20 CEST 2008 + * Copyright 2008 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * 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 "sample.h" + +#include +#include + +#include + +Sample::Sample(char *file) +{ + SF_INFO sf_info; + SNDFILE *fh = sf_open(file, SFM_READ, &sf_info); + + size = sf_seek(fh, 0, SEEK_END); + data = (jack_default_audio_sample_t*)malloc(sizeof(jack_default_audio_sample_t)*size); + + printf("Loading %s, %d samples\n", file, size); + + sf_seek(fh, 0, SEEK_SET); + sf_read_float(fh, data, size); + + sf_close(fh); +} + +Sample::~Sample() +{ + free(data); + data = NULL; + size = 0; +} diff --git a/src/sample.h b/src/sample.h new file mode 100644 index 0000000..16ff2fe --- /dev/null +++ b/src/sample.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * sample.h + * + * Mon Jul 21 10:23:20 CEST 2008 + * Copyright 2008 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * 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. + */ +#ifndef __DRUMGIZMO_SAMPLE_H__ +#define __DRUMGIZMO_SAMPLE_H__ + +#include + +class Sample { +public: + Sample(char *file); + ~Sample(); + + jack_default_audio_sample_t *data; + size_t size; +}; + +#endif/*__DRUMGIZMO_SAMPLE_H__*/ -- cgit v1.2.3