mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +01:00
* bugfix: SMFSource: track footer overwrote the last MIDI event
git-svn-id: svn://localhost/ardour2/branches/3.0@3319 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
cb88f8cce9
commit
8557d0c69f
3 changed files with 49 additions and 16 deletions
|
|
@ -111,7 +111,17 @@ class SMFSource : public MidiSource {
|
||||||
|
|
||||||
int open();
|
int open();
|
||||||
void close();
|
void close();
|
||||||
void seek_to_end();
|
|
||||||
|
/**
|
||||||
|
* This method is only used by flush_footer() to find the right seek position
|
||||||
|
* for the footer (at the end after recording or -4 offset ro SEEK_END
|
||||||
|
* if a footer is already present)
|
||||||
|
*/
|
||||||
|
void seek_to_footer_position();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the track footer at the current seek position
|
||||||
|
*/
|
||||||
void write_footer();
|
void write_footer();
|
||||||
|
|
||||||
void write_chunk_header(const char id[4], uint32_t length);
|
void write_chunk_header(const char id[4], uint32_t length);
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,8 @@ SMFSource::open()
|
||||||
|
|
||||||
// Write a tentative header just to pad things out so writing happens in the right spot
|
// Write a tentative header just to pad things out so writing happens in the right spot
|
||||||
flush_header();
|
flush_header();
|
||||||
flush_footer();
|
// this is the first footer written, so we dont need to seek for the footer
|
||||||
|
write_footer();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (_fd == 0) ? -1 : 0;
|
return (_fd == 0) ? -1 : 0;
|
||||||
|
|
@ -188,9 +189,24 @@ SMFSource::close()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SMFSource::seek_to_end()
|
SMFSource::seek_to_footer_position()
|
||||||
{
|
{
|
||||||
|
uint8_t buffer[4];
|
||||||
|
|
||||||
|
// lets check if there is a track end marker at the end of the data
|
||||||
fseek(_fd, -4, SEEK_END);
|
fseek(_fd, -4, SEEK_END);
|
||||||
|
size_t read_bytes = fread(buffer, sizeof(uint8_t), 4, _fd);
|
||||||
|
if( (read_bytes == 4) &&
|
||||||
|
buffer[0] == 0x00 &&
|
||||||
|
buffer[1] == 0xFF &&
|
||||||
|
buffer[2] == 0x2F &&
|
||||||
|
buffer[3] == 0x00) {
|
||||||
|
// there is one, so overwrite it
|
||||||
|
fseek(_fd, -4, SEEK_END);
|
||||||
|
} else {
|
||||||
|
// there is none, so append
|
||||||
|
fseek(_fd, 0, SEEK_END);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -198,7 +214,7 @@ SMFSource::flush_header()
|
||||||
{
|
{
|
||||||
// FIXME: write timeline position somehow?
|
// FIXME: write timeline position somehow?
|
||||||
|
|
||||||
//cerr << "SMF Flushing header\n";
|
//cerr << path() << " SMF Flushing header\n";
|
||||||
|
|
||||||
assert(_fd);
|
assert(_fd);
|
||||||
|
|
||||||
|
|
@ -225,7 +241,8 @@ SMFSource::flush_header()
|
||||||
int
|
int
|
||||||
SMFSource::flush_footer()
|
SMFSource::flush_footer()
|
||||||
{
|
{
|
||||||
seek_to_end();
|
//cerr << path() << " SMF Flushing footer\n";
|
||||||
|
seek_to_footer_position();
|
||||||
write_footer();
|
write_footer();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -332,18 +349,15 @@ SMFSource::read_event(uint32_t* delta_t, uint32_t* size, Byte** buf) const
|
||||||
|
|
||||||
*size = event_size;
|
*size = event_size;
|
||||||
|
|
||||||
/*if (ev.buffer == NULL)
|
|
||||||
ev.buffer = (Byte*)malloc(sizeof(Byte) * ev.size);*/
|
|
||||||
|
|
||||||
(*buf)[0] = (unsigned char)status;
|
(*buf)[0] = (unsigned char)status;
|
||||||
if (event_size > 1)
|
if (event_size > 1)
|
||||||
fread((*buf) + 1, 1, *size - 1, _fd);
|
fread((*buf) + 1, 1, *size - 1, _fd);
|
||||||
|
|
||||||
/*printf("%s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size);
|
/*printf("SMFSource %s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size);
|
||||||
for (size_t i=0; i < *size; ++i) {
|
for (size_t i=0; i < *size; ++i) {
|
||||||
printf("%X ", (*buf)[i]);
|
printf("%X ", (*buf)[i]);
|
||||||
}
|
}
|
||||||
printf("\n");*/
|
printf("\n"); */
|
||||||
|
|
||||||
return (int)*size;
|
return (int)*size;
|
||||||
}
|
}
|
||||||
|
|
@ -451,6 +465,11 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
||||||
time -= _timeline_position;
|
time -= _timeline_position;
|
||||||
|
|
||||||
const MIDI::Event ev(time, size, buf);
|
const MIDI::Event ev(time, size, buf);
|
||||||
|
if (! (ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex()) ) {
|
||||||
|
//cerr << "SMFSource: WARNING: caller tried to write non SMF-Event of type " << std::hex << int(ev.buffer()[0]) << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
append_event_unlocked(Frames, ev);
|
append_event_unlocked(Frames, ev);
|
||||||
|
|
||||||
if (_model)
|
if (_model)
|
||||||
|
|
@ -472,12 +491,12 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
||||||
void
|
void
|
||||||
SMFSource::append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev)
|
SMFSource::append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev)
|
||||||
{
|
{
|
||||||
/*printf("%s - append chan = %u, time = %lf, size = %u, data = ",
|
/*printf("SMFSource: %s - append_event_unlocked chan = %u, time = %lf, size = %u, data = ",
|
||||||
name().c_str(), (unsigned)ev.channel(), ev.time(), ev.size());
|
name().c_str(), (unsigned)ev.channel(), ev.time(), ev.size()); */
|
||||||
for (size_t i=0; i < ev.size(); ++i) {
|
for (size_t i=0; i < ev.size(); ++i) {
|
||||||
printf("%X ", ev.buffer()[i]);
|
printf("%X ", ev.buffer()[i]);
|
||||||
}
|
}
|
||||||
printf("\n");*/
|
printf("\n");
|
||||||
|
|
||||||
assert(ev.time() >= 0);
|
assert(ev.time() >= 0);
|
||||||
assert(ev.time() >= _last_ev_time);
|
assert(ev.time() >= _last_ev_time);
|
||||||
|
|
|
||||||
|
|
@ -181,13 +181,17 @@ struct Event {
|
||||||
inline uint8_t velocity() const { return (_buffer[2]); }
|
inline uint8_t velocity() const { return (_buffer[2]); }
|
||||||
inline uint8_t cc_number() const { return (_buffer[1]); }
|
inline uint8_t cc_number() const { return (_buffer[1]); }
|
||||||
inline uint8_t cc_value() const { return (_buffer[2]); }
|
inline uint8_t cc_value() const { return (_buffer[2]); }
|
||||||
inline uint16_t pitch_bender_value() const { return (((0x7F & _buffer[1]) << 7) | (0x7F & _buffer[2])); }
|
|
||||||
inline uint8_t pitch_bender_lsb() const { return (_buffer[1]); }
|
inline uint8_t pitch_bender_lsb() const { return (_buffer[1]); }
|
||||||
inline uint8_t pitch_bender_msb() const { return (_buffer[2]); }
|
inline uint8_t pitch_bender_msb() const { return (_buffer[2]); }
|
||||||
|
inline uint16_t pitch_bender_value() const { return (((0x7F & _buffer[2]) << 7) | (0x7F & _buffer[1])); }
|
||||||
inline uint8_t pgm_number() const { return (_buffer[1]); }
|
inline uint8_t pgm_number() const { return (_buffer[1]); }
|
||||||
inline void set_pgm_number(uint8_t number){ _buffer[1] = number; }
|
inline void set_pgm_number(uint8_t number){ _buffer[1] = number; }
|
||||||
inline uint8_t aftertouch() const { return (_buffer[1]); }
|
inline uint8_t aftertouch() const { return (_buffer[1]); }
|
||||||
inline uint8_t channel_aftertouch() const { return (_buffer[1]); }
|
inline uint8_t channel_aftertouch() const { return (_buffer[1]); }
|
||||||
|
// midi channel events range from 0x80 to 0xE0
|
||||||
|
inline bool is_channel_event() const { return (0x80 <= type()) && (type() <= 0xE0); }
|
||||||
|
inline bool is_smf_meta_event() const { return _buffer[0] == 0xFF; }
|
||||||
|
inline bool is_sysex() const { return _buffer[0] == 0xF0 || _buffer[0] == 0xF7; }
|
||||||
inline const uint8_t* buffer() const { return _buffer; }
|
inline const uint8_t* buffer() const { return _buffer; }
|
||||||
inline uint8_t*& buffer() { return _buffer; }
|
inline uint8_t*& buffer() { return _buffer; }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue