diff options
author | David Robillard <d@drobilla.net> | 2008-05-23 03:41:45 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-05-23 03:41:45 +0000 |
commit | 6ebefb4c8b523ecac35b7440907ef9e57d0154f0 (patch) | |
tree | cb2f25b531b9b38a642767a7fd21c5f285ca4623 /raul | |
parent | 264ce503aebaa87d275f23d1ea1a33034083b190 (diff) | |
download | raul-6ebefb4c8b523ecac35b7440907ef9e57d0154f0.tar.gz raul-6ebefb4c8b523ecac35b7440907ef9e57d0154f0.tar.bz2 raul-6ebefb4c8b523ecac35b7440907ef9e57d0154f0.zip |
Merge improvemennts to MIDI stuff from Ardour.
git-svn-id: http://svn.drobilla.net/lad/raul@1227 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'raul')
-rw-r--r-- | raul/RingBuffer.hpp | 114 | ||||
-rw-r--r-- | raul/SMFReader.hpp | 43 | ||||
-rw-r--r-- | raul/midi_names.h | 94 |
3 files changed, 162 insertions, 89 deletions
diff --git a/raul/RingBuffer.hpp b/raul/RingBuffer.hpp index 4098a2f..dff1464 100644 --- a/raul/RingBuffer.hpp +++ b/raul/RingBuffer.hpp @@ -1,5 +1,5 @@ /* This file is part of Raul. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * Copyright (C) 2007-2008 Dave Robillard <http://drobilla.net> * * Raul 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 @@ -19,6 +19,7 @@ #define RAUL_RING_BUFFER_HPP #include <cassert> +#include <iostream> #include <glib.h> namespace Raul { @@ -62,7 +63,7 @@ public: if (w > r) { return ((r - w + _size) % _size) - 1; - } else if(w < r) { + } else if (w < r) { return (r - w) - 1; } else { return _size - 1; @@ -83,20 +84,65 @@ public: size_t capacity() const { return _size; } + size_t peek(size_t size, T* dst); + bool full_peek(size_t size, T* dst); + size_t read(size_t size, T* dst); - void write(size_t size, const T* src); - bool full_read(size_t size, T* dst); + bool skip(size_t size); + + void write(size_t size, const T* src); + protected: - mutable gint _write_ptr; - mutable gint _read_ptr; + mutable int _write_ptr; + mutable int _read_ptr; size_t _size; ///< Size (capacity) in bytes - T* _buf; ///< size, event, size, event... + T* _buf; ///< size, event, size, event... }; +/** Peek at the ringbuffer (read w/o advancing read pointer). + * + * Note that a full read may not be done if the data wraps around. + * Caller must check return value and call again if necessary, or use the + * full_peek method which does this automatically. + */ +template<typename T> +size_t +RingBuffer<T>::peek(size_t size, T* dst) +{ + const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + + const size_t read_size = (priv_read_ptr + size < _size) + ? size + : _size - priv_read_ptr; + + memcpy(dst, &_buf[priv_read_ptr], read_size); + + return read_size; +} + + +template<typename T> +bool +RingBuffer<T>::full_peek(size_t size, T* dst) +{ + if (read_space() < size) { + return false; + } + + const size_t read_size = peek(size, dst); + + if (read_size < size) { + peek(size - read_size, dst + read_size); + } + + return true; +} + + /** Read from the ringbuffer. * * Note that a full read may not be done if the data wraps around. @@ -122,6 +168,40 @@ RingBuffer<T>::read(size_t size, T* dst) template<typename T> +bool +RingBuffer<T>::full_read(size_t size, T* dst) +{ + if (read_space() < size) { + return false; + } + + const size_t read_size = read(size, dst); + + if (read_size < size) { + read(size - read_size, dst + read_size); + } + + return true; +} + + +template<typename T> +bool +RingBuffer<T>::skip(size_t size) +{ + if (read_space() < size) { + std::cerr << "WARNING: Attempt to skip past end of MIDI ring buffer" << std::endl; + return false; + } + + const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + g_atomic_int_set(&_read_ptr, (priv_read_ptr + size) % _size); + + return true; +} + + +template<typename T> inline void RingBuffer<T>::write(size_t size, const T* src) { @@ -129,33 +209,17 @@ RingBuffer<T>::write(size_t size, const T* src) if (priv_write_ptr + size <= _size) { memcpy(&_buf[priv_write_ptr], src, size); - g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size); + g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size); } else { const size_t this_size = _size - priv_write_ptr; assert(this_size < size); assert(priv_write_ptr + this_size <= _size); memcpy(&_buf[priv_write_ptr], src, this_size); memcpy(&_buf[0], src+this_size, size - this_size); - g_atomic_int_set(&_write_ptr, size - this_size); + g_atomic_int_set(&_write_ptr, size - this_size); } } - -template<typename T> -bool -RingBuffer<T>::full_read(size_t size, T* dst) -{ - if (read_space() < size) - return false; - - const size_t read_size = read(size, dst); - - if (read_size < size) - read(size - read_size, dst + read_size); - - return true; -} - } // namespace Raul diff --git a/raul/SMFReader.hpp b/raul/SMFReader.hpp index 7ce6f5b..1bd1f0d 100644 --- a/raul/SMFReader.hpp +++ b/raul/SMFReader.hpp @@ -32,39 +32,48 @@ namespace Raul { */ class SMFReader { public: - SMFReader(); + class PrematureEOF : public std::exception { + const char* what() const throw() { return "Unexpected end of file"; } + }; + class CorruptFile : public std::exception { + const char* what() const throw() { return "Corrupted file"; } + }; + class UnsupportedTime : public std::exception { + const char* what() const throw() { return "Unsupported time stamp type (SMPTE)"; } + }; + + SMFReader(const std::string filename=""); ~SMFReader(); - bool open(const std::string& filename); + bool open(const std::string& filename) throw (std::logic_error, UnsupportedTime); bool seek_to_track(unsigned track) throw (std::logic_error); - TimeUnit unit() const { return _unit; } uint16_t type() const { return _type; } uint16_t ppqn() const { return _ppqn; } size_t num_tracks() { return _num_tracks; } - int read_event(size_t buf_len, - uint8_t* buf, - uint32_t* ev_size, - TimeStamp* ev_delta_time) throw (std::logic_error); + int read_event(size_t buf_len, + uint8_t* buf, + uint32_t* ev_size, + uint32_t* ev_delta_time) + throw (std::logic_error, PrematureEOF, CorruptFile); void close(); + + static uint32_t read_var_len(FILE* fd) throw (PrematureEOF); protected: /** size of SMF header, including MTrk chunk header */ static const uint32_t HEADER_SIZE = 22; - uint32_t read_var_len() const; - - std::string _filename; - FILE* _fd; - TimeUnit _unit; - uint16_t _type; - uint16_t _ppqn; - uint16_t _num_tracks; - uint32_t _track; - uint32_t _track_size; + std::string _filename; + FILE* _fd; + uint16_t _type; + uint16_t _ppqn; + uint16_t _num_tracks; + uint32_t _track; + uint32_t _track_size; }; diff --git a/raul/midi_names.h b/raul/midi_names.h index 1b98f9a..114c299 100644 --- a/raul/midi_names.h +++ b/raul/midi_names.h @@ -81,69 +81,69 @@ inline static const char* midi_name(uint8_t status) return "Reset"; break; case MIDI_CTL_MSB_BANK: - return "Bank Selection"; break; + return "Bank Select (Coarse)"; break; case MIDI_CTL_MSB_MODWHEEL: - return "Modulation"; break; + return "Modulation (Coarse)"; break; case MIDI_CTL_MSB_BREATH: - return "Breath"; break; + return "Breath (Coarse)"; break; case MIDI_CTL_MSB_FOOT: - return "Foot"; break; + return "Foot (Coarse)"; break; case MIDI_CTL_MSB_PORTAMENTO_TIME: - return "Portamento Time"; break; + return "Portamento Time (Coarse)"; break; case MIDI_CTL_MSB_DATA_ENTRY: - return "Data Entry"; break; + return "Data Entry (Coarse)"; break; case MIDI_CTL_MSB_MAIN_VOLUME: - return "Main Volume"; break; + return "Main Volume (Coarse)"; break; case MIDI_CTL_MSB_BALANCE: - return "Balance"; break; + return "Balance (Coarse)"; break; case MIDI_CTL_MSB_PAN: - return "Panpot"; break; + return "Pan (Coarse)"; break; case MIDI_CTL_MSB_EXPRESSION: - return "Expression"; break; + return "Expression (Coarse)"; break; case MIDI_CTL_MSB_EFFECT1: - return "Effect1"; break; + return "Effect 1 (Coarse)"; break; case MIDI_CTL_MSB_EFFECT2: - return "Effect2"; break; + return "Effect 2 (Coarse)"; break; case MIDI_CTL_MSB_GENERAL_PURPOSE1: - return "General Purpose 1"; break; + return "General Purpose 1 (Coarse)"; break; case MIDI_CTL_MSB_GENERAL_PURPOSE2: - return "General Purpose 2"; break; + return "General Purpose 2 (Coarse)"; break; case MIDI_CTL_MSB_GENERAL_PURPOSE3: - return "General Purpose 3"; break; + return "General Purpose 3 (Coarse)"; break; case MIDI_CTL_MSB_GENERAL_PURPOSE4: - return "General Purpose 4"; break; + return "General Purpose 4 (Coarse)"; break; case MIDI_CTL_LSB_BANK: - return "Bank Selection"; break; + return "Bank Select (Fine)"; break; case MIDI_CTL_LSB_MODWHEEL: - return "Modulation"; break; + return "Modulation (Fine)"; break; case MIDI_CTL_LSB_BREATH: - return "Breath"; break; + return "Breath (Fine)"; break; case MIDI_CTL_LSB_FOOT: - return "Foot"; break; + return "Foot (Fine)"; break; case MIDI_CTL_LSB_PORTAMENTO_TIME: - return "Portamento Time"; break; + return "Portamento Time (Fine)"; break; case MIDI_CTL_LSB_DATA_ENTRY: - return "Data Entry"; break; + return "Data Entry (Fine)"; break; case MIDI_CTL_LSB_MAIN_VOLUME: - return "Main Volume"; break; + return "Main Volume (Fine)"; break; case MIDI_CTL_LSB_BALANCE: - return "Balance"; break; + return "Balance (Fine)"; break; case MIDI_CTL_LSB_PAN: - return "Panpot"; break; + return "Pan (Fine)"; break; case MIDI_CTL_LSB_EXPRESSION: - return "Expression"; break; + return "Expression (Fine)"; break; case MIDI_CTL_LSB_EFFECT1: - return "Effect1"; break; + return "Effect 1 (Fine)"; break; case MIDI_CTL_LSB_EFFECT2: - return "Effect2"; break; + return "Effect 2 (Fine)"; break; case MIDI_CTL_LSB_GENERAL_PURPOSE1: - return "General Purpose 1"; break; + return "General Purpose 1 (Fine)"; break; case MIDI_CTL_LSB_GENERAL_PURPOSE2: - return "General Purpose 2"; break; + return "General Purpose 2 (Fine)"; break; case MIDI_CTL_LSB_GENERAL_PURPOSE3: - return "General Purpose 3"; break; + return "General Purpose 3 (Fine)"; break; case MIDI_CTL_LSB_GENERAL_PURPOSE4: - return "General Purpose 4"; break; + return "General Purpose 4 (Fine)"; break; case MIDI_CTL_SUSTAIN: return "Sustain Pedal"; break; case MIDI_CTL_PORTAMENTO: @@ -157,25 +157,25 @@ inline static const char* midi_name(uint8_t status) case MIDI_CTL_HOLD2: return "Hold2"; break; case MIDI_CTL_SC1_SOUND_VARIATION: - return "SC1 Sound Variation"; break; + return "Sound Variation"; break; case MIDI_CTL_SC2_TIMBRE: - return "SC2 Timbre"; break; + return "Sound Timbre"; break; case MIDI_CTL_SC3_RELEASE_TIME: - return "SC3 Release Time"; break; + return "Sound Release Time"; break; case MIDI_CTL_SC4_ATTACK_TIME: - return "SC4 Attack Time"; break; + return "Sound Attack Time"; break; case MIDI_CTL_SC5_BRIGHTNESS: - return "SC5 Brightness"; break; + return "Sound Brightness"; break; case MIDI_CTL_SC6: - return "SC6"; break; + return "Sound Control 6"; break; case MIDI_CTL_SC7: - return "SC7"; break; + return "Sound Control 7"; break; case MIDI_CTL_SC8: - return "SC8"; break; + return "Sound Control 8"; break; case MIDI_CTL_SC9: - return "SC9"; break; + return "Sound Control 9"; break; case MIDI_CTL_SC10: - return "SC10"; break; + return "Sound Control 10"; break; case MIDI_CTL_GENERAL_PURPOSE5: return "General Purpose 5"; break; case MIDI_CTL_GENERAL_PURPOSE6: @@ -187,15 +187,15 @@ inline static const char* midi_name(uint8_t status) case MIDI_CTL_PORTAMENTO_CONTROL: return "Portamento Control"; break; case MIDI_CTL_E1_REVERB_DEPTH: - return "E1 Reverb Depth"; break; + return "Reverb Depth"; break; case MIDI_CTL_E2_TREMOLO_DEPTH: - return "E2 Tremolo Depth"; break; + return "Tremolo Depth"; break; case MIDI_CTL_E3_CHORUS_DEPTH: - return "E3 Chorus Depth"; break; + return "Chorus Depth"; break; case MIDI_CTL_E4_DETUNE_DEPTH: - return "E4 Detune Depth"; break; + return "Detune Depth"; break; case MIDI_CTL_E5_PHASER_DEPTH: - return "E5 Phaser Depth"; break; + return "Phaser Depth"; break; case MIDI_CTL_DATA_INCREMENT: return "Data Increment"; break; case MIDI_CTL_DATA_DECREMENT: |