diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed3cde15c..6b1a46f54 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -835,9 +835,7 @@ set( FASTMATH_SOURCES gl/models/gl_models.cpp r_data/models/models.cpp r_data/matrix.cpp -# These will be removed later. - sound/timiditypp/w32_a.cpp - + ) set (PCH_SOURCES @@ -1172,7 +1170,6 @@ set (PCH_SOURCES sound/timidity/playmidi.cpp sound/timidity/resample.cpp sound/timidity/timidity.cpp - sound/timiditypp/aq.cpp sound/timiditypp/common.cpp sound/timiditypp/configfile.cpp sound/timiditypp/effect.cpp @@ -1181,7 +1178,6 @@ set (PCH_SOURCES sound/timiditypp/instrum.cpp sound/timiditypp/mblock.cpp sound/timiditypp/mix.cpp - sound/timiditypp/output.cpp sound/timiditypp/playmidi.cpp sound/timiditypp/quantity.cpp sound/timiditypp/readmidic.cpp diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index 55cedb34b..b90959c99 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -214,7 +214,7 @@ void TimidityPPMIDIDevice::HandleLongEvent(const uint8_t *data, int len) void TimidityPPMIDIDevice::ComputeOutput(float *buffer, int len) { if (Renderer != nullptr) - Renderer->get_output(buffer, len); + Renderer->compute_data(buffer, len); sampletime += len; } diff --git a/src/sound/timiditypp/aq.cpp b/src/sound/timiditypp/aq.cpp deleted file mode 100644 index c95d184cb..000000000 --- a/src/sound/timiditypp/aq.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* - TiMidity++ -- MIDI to WAVE converter and player - Copyright (C) 1999-2002 Masanao Izumo - Copyright (C) 1995 Tuukka Toivonen - - 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - aq.c - Audio queue. - Written by Masanao Izumo -*/ - -#include -#include -#include - -#include "timidity.h" -#include "common.h" -#include "aq.h" -#include "instrum.h" -#include "playmidi.h" -#include "effect.h" - - -namespace TimidityPlus -{ - - -#define TEST_SPARE_RATE 0.9 -#define MAX_BUCKET_TIME 0.2 -#define MAX_FILLED_TIME 2.0 - - -AudioQueue::AudioQueue(PlayMode *pm, int bufsize, Reverb *reverb) -{ - playMode = pm; - buffer_size = bufsize; - effect = new Effect(reverb); -} - -AudioQueue::~AudioQueue() -{ - freeSoftQueue(); - delete effect; -} - -void AudioQueue::setup(void) -{ - int ch = 2; // stereo only - - /* Initialize Bps, bucket_size, device_qsize, and bucket_time */ - - if (playMode->encoding & PE_24BIT) - Bps = 3 * ch; - else - Bps = 2 * ch; - - bucket_size = buffer_size * Bps; - bucket_time = (double)bucket_size / Bps / playMode->rate; - - device_qsize = 0; - freeSoftQueue(); - nbuckets = 0; - - effect->init_effect(); - aq_add_count = 0; -} - -void AudioQueue::setSoftQueue(double soft_buff_time, double fill_start_time) -{ - int nb; - - /* for re-initialize */ - if (soft_buff_time < 0) - soft_buff_time = last_soft_buff_time; - if (fill_start_time < 0) - fill_start_time = last_fill_start_time; - - nb = (int)(soft_buff_time / bucket_time); - if (nb == 0) - aq_start_count = 0; - else - aq_start_count = (int32_t)(fill_start_time * playMode->rate); - aq_fill_buffer_flag = (aq_start_count > 0); - - if (nbuckets != nb) - { - nbuckets = nb; - allocSoftQueue(); - } - - last_soft_buff_time = soft_buff_time; - last_fill_start_time = fill_start_time; -} - -/* Send audio data to playMode->output_data() */ -int AudioQueue::outputData(char *buff, int nbytes) -{ - int i; - - play_counter += nbytes / Bps; - - while (nbytes > 0) - { - i = nbytes; - if (i > bucket_size) - i = bucket_size; - if (playMode->output_data(buff, i) == -1) - return -1; - nbytes -= i; - buff += i; - } - - return 0; -} - -int AudioQueue::add(int32_t *samples, int32_t count) -{ - int32_t nbytes, i; - char *buff; - - if (!count) - { - return 0; - } - - aq_add_count += count; - effect->do_effect(samples, count); - nbytes = general_output_convert(samples, count); - buff = (char *)samples; - - if (device_qsize == 0) - return playMode->output_data(buff, nbytes); - - aq_fill_buffer_flag = (aq_add_count <= aq_start_count); - - while ((i = addPlayBucket(buff, nbytes)) < nbytes) - { - buff += i; - nbytes -= i; - if (head && head->len == bucket_size) - { - if (fillOne() == -1) - return -1; - } - aq_fill_buffer_flag = 0; - } - return 0; -} - -/* alloc_soft_queue() (re-)initializes audio buckets. */ -void AudioQueue::allocSoftQueue(void) -{ - int i; - char *base; - - freeSoftQueue(); - - base_buckets = new AudioBucket[nbuckets]; - base = new char[nbuckets * bucket_size]; - for (i = 0; i < nbuckets; i++) - base_buckets[i].data = base + i * bucket_size; - flushBuckets(); -} - -void AudioQueue::freeSoftQueue(void) -{ - if (base_buckets) - { - delete[] base_buckets[0].data; - delete[] base_buckets; - base_buckets = NULL; - } -} - -/* aq_fill_one() transfers one audio bucket to device. */ -int AudioQueue::fillOne(void) -{ - AudioBucket *tmp; - - if (head == NULL) - return 0; - if (outputData(head->data, bucket_size) == -1) - return -1; - tmp = head; - head = head->next; - reuseAudioBucket(tmp); - return 0; -} - -int32_t AudioQueue::softFilled(void) -{ - int32_t bytes; - AudioBucket *cur; - - bytes = 0; - for (cur = head; cur != NULL; cur = cur->next) - bytes += cur->len; - return bytes / Bps; -} - -int AudioQueue::softFlush(void) -{ - while (head) - { - if (head->len < bucket_size) - { - /* Add silence code */ - memset(head->data + head->len, 0, bucket_size - head->len); - head->len = bucket_size; - } - if (fillOne() == -1) - return RC_ERROR; - } - return RC_OK; -} - -int AudioQueue::flush(int discard) -{ - aq_add_count = 0; - effect->init_effect(); - - if (discard) - { - if (playMode->acntl(PM_REQ_DISCARD, NULL) != -1) - { - flushBuckets(); - return RC_OK; - } - } - - playMode->acntl(PM_REQ_FLUSH, NULL); - flushBuckets(); - return RC_OK; -} - -/* add_play_bucket() attempts to add buf to audio bucket. - * It returns actually added bytes. - */ -int AudioQueue::addPlayBucket(const char *buf, int n) -{ - int total; - - if (n == 0) - return 0; - - if (!nbuckets) { - playMode->output_data((char *)buf, n); - return n; - } - - if (head == NULL) - head = tail = nextAllocatedBucket(); - - total = 0; - while (n > 0) - { - int i; - - if (tail->len == bucket_size) - { - AudioBucket *b; - if ((b = nextAllocatedBucket()) == NULL) - break; - if (head == NULL) - head = tail = b; - else - tail = tail->next = b; - } - - i = bucket_size - tail->len; - if (i > n) - i = n; - memcpy(tail->data + tail->len, buf + total, i); - total += i; - n -= i; - tail->len += i; - } - - return total; -} - -/* Flush and clear audio bucket */ -void AudioQueue::flushBuckets(void) -{ - int i; - - allocated_bucket_list = NULL; - for (i = 0; i < nbuckets; i++) - reuseAudioBucket(&base_buckets[i]); - head = tail = NULL; - aq_fill_buffer_flag = (aq_start_count > 0); - play_counter = play_offset_counter = 0; -} - -/* next_allocated_bucket() gets free bucket. If all buckets is used, it - * returns NULL. - */ -AudioQueue::AudioBucket *AudioQueue::nextAllocatedBucket(void) -{ - AudioBucket *b; - - if (allocated_bucket_list == NULL) - return NULL; - b = allocated_bucket_list; - allocated_bucket_list = allocated_bucket_list->next; - b->len = 0; - b->next = NULL; - return b; -} - -/* Reuse specified bucket */ -void AudioQueue::reuseAudioBucket(AudioBucket *bucket) -{ - bucket->next = allocated_bucket_list; - allocated_bucket_list = bucket; -} -} \ No newline at end of file diff --git a/src/sound/timiditypp/aq.h b/src/sound/timiditypp/aq.h deleted file mode 100644 index 349807e20..000000000 --- a/src/sound/timiditypp/aq.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - TiMidity++ -- MIDI to WAVE converter and player - Copyright (C) 1999-2002 Masanao Izumo - Copyright (C) 1995 Tuukka Toivonen - - 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - aq.h - Audio queue. - Written by Masanao Izumo -*/ - -#ifndef ___AQ_H_ -#define ___AQ_H_ - -#include - -namespace TimidityPlus -{ - -/* interfaces */ - -class Effect; -class Reverb; -struct PlayMode; - -class AudioQueue -{ - struct AudioBucket - { - char *data; - int len; - AudioBucket *next; - }; - - Effect *effect; - PlayMode *playMode; - - int buffer_size = 0; - int32_t device_qsize = 0; - int Bps = 0; /* Bytes per sample frame */ - int bucket_size = 0; - int nbuckets = 0; - double bucket_time = 0; - int aq_fill_buffer_flag = 0; - int32_t aq_start_count = 0; - int32_t aq_add_count = 0; - - int32_t play_counter = 0, play_offset_counter = 0; - double play_start_time = 0; - - AudioBucket *base_buckets = NULL; - AudioBucket *allocated_bucket_list = NULL; - AudioBucket *head = NULL; - AudioBucket *tail = NULL; - - void allocSoftQueue(void); - int addPlayBucket(const char *buf, int n); - void reuseAudioBucket(AudioBucket *bucket); - AudioBucket *nextAllocatedBucket(void); - void flushBuckets(void); - int fillOne(void); - int outputData(char *buff, int nbytes); - - double last_soft_buff_time, last_fill_start_time; - -public: - AudioQueue(PlayMode *pm, int buffersize, Reverb *reverb); // play_mode, audio_buffer_size - ~AudioQueue(); - - void setup(); // allocates the buffer for software queue, and estimate maxmum queue size of audio device. - void setSoftQueue(double soft_buff_time, double fill_start_time); // makes software audio queue. If fill_start_time is positive, TiMidity doesn't start playing immidiately until the autio buffer is filled. - int add(int32_t *samples, int32_t count); // adds new samples to software queue. If samples is NULL, only updates internal software queue buffer. - int32_t softFilled(void); // returns filled queue length of software buffer. - int flush(int discard); // If discard is true, discards all audio queue and returns immediately, otherwise waits until play all out. - int softFlush(void); // transfers all buffer to device - void freeSoftQueue(void); // free soft_que memory - - int fillBufferFlag() // non-zero if aq->add() is in filling mode - { - return aq_fill_buffer_flag; - } -}; - -} -#endif /* ___AQ_H_ */ diff --git a/src/sound/timiditypp/output.cpp b/src/sound/timiditypp/output.cpp deleted file mode 100644 index 2448f0ac2..000000000 --- a/src/sound/timiditypp/output.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - TiMidity++ -- MIDI to WAVE converter and player - Copyright (C) 1999-2002 Masanao Izumo - Copyright (C) 1995 Tuukka Toivonen - - 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - output.c - - Audio output (to file / device) functions. -*/ - -#include "timidity.h" -#include "common.h" -#include "sysdep.h" -#include "tables.h" - -namespace TimidityPlus -{ - - -int audio_buffer_bits = DEFAULT_AUDIO_BUFFER_BITS; - -extern PlayMode w32_play_mode; -#define DEV_PLAY_MODE &w32_play_mode - -extern PlayMode raw_play_mode; - - -PlayMode *play_mode = DEV_PLAY_MODE; - -/*****************************************************************/ -/* Some functions to convert signed 32-bit data to other formats */ - -void s32tos16(int32_t *lp, int32_t c) -{ - int16_t *sp=(int16_t *)(lp); - int32_t l, i; - - for(i = 0; i < c; i++) - { - l=(lp[i])>>(32-16-GUARD_BITS); - if (l > 32767) l=32767; - else if (l<-32768) l=-32768; - sp[i] = (int16_t)(l); - } -} - -// This only gets used as intermediate so we do not care about byte order -#define STORE_S24(cp, l) *cp++ = l & 0xFF, *cp++ = l >> 8 & 0xFF, *cp++ = l >> 16 -#define MAX_24BIT_SIGNED (8388607) -#define MIN_24BIT_SIGNED (-8388608) - -void s32tos24(int32_t *lp, int32_t c) -{ - uint8_t *cp = (uint8_t *)(lp); - int32_t l, i; - - for(i = 0; i < c; i++) - { - l = (lp[i]) >> (32 - 24 - GUARD_BITS); - l = (l > MAX_24BIT_SIGNED) ? MAX_24BIT_SIGNED - : (l < MIN_24BIT_SIGNED) ? MIN_24BIT_SIGNED : l; - STORE_S24(cp, l); - } -} - -/* return: number of bytes */ -int32_t general_output_convert(int32_t *buf, int32_t count) -{ - int32_t bytes; - - count *= 2; /* Stereo samples */ - bytes = count; - bytes *= 2; - s32tos16(buf, count); - return bytes; -} - -} \ No newline at end of file diff --git a/src/sound/timiditypp/output.h b/src/sound/timiditypp/output.h deleted file mode 100644 index 804f8745f..000000000 --- a/src/sound/timiditypp/output.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - TiMidity++ -- MIDI to WAVE converter and player - Copyright (C) 1999-2002 Masanao Izumo - Copyright (C) 1995 Tuukka Toivonen - - 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - output.h - -*/ - -#ifndef ___OUTPUT_H_ -#define ___OUTPUT_H_ - -namespace TimidityPlus -{ - - - -/* Data format encoding bits */ -#define PE_16BIT (1u<<2) /* versus 8-bit */ -#define PE_24BIT (1u<<6) /* versus 8-bit, 16-bit */ - -/* for play_mode->acntl() */ -enum { - PM_REQ_DISCARD, /* ARG: not-used - * Discard the audio device buffer and returns - * immediatly. - */ - - PM_REQ_FLUSH, /* ARG: not-used - * Wait until all audio data is out. - */ - -}; - - -/* Flag bits */ -#define PF_PCM_STREAM (1u<<0) /* Enable output PCM data */ -#define PF_BUFF_FRAGM_OPT (1u<<3) /* Enable set extra_param[0] to specify - the number of audio buffer fragments */ -#define PF_AUTO_SPLIT_FILE (1u<<4) /* Split PCM files automatically */ -#define PF_FILE_OUTPUT (1u<<5) /* Output is to file rather than device */ - -struct PlayMode { - int32_t rate, encoding, flag; - int fd; /* file descriptor for the audio device - -1 means closed otherwise opened. It must be -1 by default. */ - int32_t extra_param[5]; /* System depended parameters - e.g. buffer fragments, ... */ - const char *id_name; - char id_character; - const char *name; /* default device or file name */ - int (* open_output)(void); /* 0=success, 1=warning, -1=fatal error */ - void (* close_output)(void); - - int (* output_data)(char *buf, int32_t bytes); - /* return: -1=error, otherwise success */ - - int (* acntl)(int request, void *arg); /* see PM_REQ_* above - * return: 0=success, -1=fail - */ - int (* detect)(void); /* 0=not available, 1=available */ -}; - -extern PlayMode *play_mode_list[], *play_mode; - -/* 16-bit */ -extern void s32tos16(int32_t *lp, int32_t c); - -/* 24-bit */ -extern void s32tos24(int32_t *lp, int32_t c); - -extern int32_t general_output_convert(int32_t *buf, int32_t count); - - -} - -#endif /* ___OUTPUT_H_ */ - diff --git a/src/sound/timiditypp/playmidi.cpp b/src/sound/timiditypp/playmidi.cpp index e821787c5..fe03b6a61 100644 --- a/src/sound/timiditypp/playmidi.cpp +++ b/src/sound/timiditypp/playmidi.cpp @@ -32,7 +32,6 @@ #include "mix.h" #include "recache.h" #include "reverb.h" -#include "aq.h" #include "freq.h" #include "quantity.h" #include "c_cvars.h" @@ -135,8 +134,6 @@ Player::Player(int freq, Instruments *instr) mixer = new Mixer(this); recache = new Recache(this); - aq = new AudioQueue(play_mode, AUDIO_BUFFER_SIZE, reverb); - aq->setup(); for (int i = 0; i < MAX_CHANNELS; i++) init_channel_layer(i); @@ -190,8 +187,6 @@ Player::~Player() reuse_mblock(&playmidi_pool); if (reverb_buffer != nullptr) free(reverb_buffer); for (int i = 0; i < MAX_CHANNELS; i++) free_drum_effect(i); - aq->flush(1); - delete aq; delete mixer; delete recache; delete effect; @@ -2670,7 +2665,8 @@ void Player::midi_program_change(int ch, int prog) channel[ch].program = (instruments->defaultProgram(ch) == SPECIAL_PROGRAM) ? SPECIAL_PROGRAM : prog; channel[ch].altassign = NULL; - if (opt_realtime_playing && (play_mode->flag & PF_PCM_STREAM)) { + if (opt_realtime_playing) + { b = channel[ch].bank, p = prog; instruments->instrument_map(channel[ch].mapID, &b, &p); play_midi_load_instrument(0, b, p); @@ -5021,46 +5017,24 @@ void Player::do_compute_data(int32_t count) current_sample += count; } -int Player::send_output(int32_t *samples, int32_t count) -{ - aq->add(samples, count); - /* - effect->do_effect(samples, count); - // pass to caller - for (int i = 0; i < count && output_len > 0; i++) - { - *output_buffer++ = (*samples++)*(1.f / 0x80000000u); - *output_buffer++ = (*samples++)*(1.f / 0x80000000u); - output_len--; - } - */ - memset(output_buffer, 0, output_len * 8); - return RC_OK; -} - -int Player::compute_data(int32_t count) +int Player::compute_data(float *buffer, int32_t count) { if (count == 0) return RC_OK; - if (!buffered_count) buffer_pointer = common_buffer; + buffer_pointer = common_buffer; - while ((count + buffered_count) >= AUDIO_BUFFER_SIZE) + while (count > 0) { - do_compute_data(AUDIO_BUFFER_SIZE - buffered_count); - count -= AUDIO_BUFFER_SIZE - buffered_count; + int process = std::min(count, AUDIO_BUFFER_SIZE); + do_compute_data(process); + count -= process; - if (aq->add(common_buffer, AUDIO_BUFFER_SIZE) == -1) - return RC_ERROR; - - buffer_pointer = common_buffer; - buffered_count = 0; - - } - if (count > 0) - { - do_compute_data(count); - buffered_count += count; - buffer_pointer += count * 2; + effect->do_effect(common_buffer, process); + // pass to caller + for (int i = 0; i < process*2; i++) + { + *buffer++ = (common_buffer[i])*(5.f / 0x80000000u); + } } return RC_OK; } @@ -5157,32 +5131,11 @@ void Player::update_legato_controls(int ch) int Player::play_event(MidiEvent *ev) { - int32_t i, j, cet; + int32_t i, j; int k, l, ch, orig_ch, port_ch, offset, layered; - //current_event = ev; - cet = MIDI_EVENT_TIME(ev); - - if (cet > current_sample) - { - int rc = RC_OK; - - if (midi_streaming != 0 && (cet - current_sample) * 1000 / playback_rate > stream_max_compute) - { - kill_all_voices(); - current_sample = cet; - } - - //Printf("Computing %d samples\n", cet - current_sample); - - rc = compute_data(cet - current_sample); - if (rc != RC_OK) - return rc; - } current_event = ev; - //Printf("Playing event %d, time %d\n", ev->type, ev->time); - #ifndef SUPPRESS_CHANNEL_LAYER orig_ch = ev->channel; layered = !IS_SYSEX_EVENT_TYPE(ev); @@ -5896,9 +5849,7 @@ void Player::playmidi_tmr_reset(void) { int i; - aq->flush(0); current_sample = 0; - buffered_count = 0; buffer_pointer = common_buffer; for(i = 0; i < MAX_CHANNELS; i++) channel[i].lasttime = 0; @@ -6061,14 +6012,6 @@ void Player::init_channel_layer(int ch) channel[ch].port_select = ch >> 4; } -void Player::get_output(float *buffer, int len) -{ - output_buffer = buffer; - output_len = len; - //Printf("Not Computing %d samples\n", len); - //compute_data(len); -} - static const struct ctl_chg_types { unsigned char mtype; diff --git a/src/sound/timiditypp/playmidi.h b/src/sound/timiditypp/playmidi.h index 5342540b3..8964f89eb 100644 --- a/src/sound/timiditypp/playmidi.h +++ b/src/sound/timiditypp/playmidi.h @@ -512,7 +512,6 @@ class Recache; class Mixer; class Reverb; class Effect; -class AudioQueue; class Player { @@ -534,7 +533,6 @@ private: Mixer *mixer; Reverb *reverb; Effect *effect; - AudioQueue *aq; MidiEvent *current_event; @@ -561,8 +559,6 @@ private: int current_freq_table; int current_temper_freq_table; int master_tuning; - float *output_buffer; - int output_len; int make_rvid_flag; /* For reverb optimization */ @@ -577,7 +573,6 @@ private: int32_t lost_notes, cut_notes; int32_t common_buffer[AUDIO_BUFFER_SIZE * 2], *buffer_pointer; /* stereo samples */ int16_t wav_buffer[AUDIO_BUFFER_SIZE * 2]; - int32_t buffered_count; int32_t insertion_effect_buffer[AUDIO_BUFFER_SIZE * 2]; @@ -663,15 +658,12 @@ private: void do_compute_data(int32_t count); int check_midi_play_end(MidiEvent *e, int len); int midi_play_end(void); - int compute_data(int32_t count); void update_modulation_wheel(int ch); void drop_portamento(int ch); void update_portamento_time(int ch); void update_legato_controls(int ch); void set_master_tuning(int tune); struct midi_file_info *new_midi_file_info(); - int send_output(int32_t *samples, int32_t count); - void adjust_amplification(void); void init_freq_table_user(void); @@ -740,7 +732,7 @@ public: void recompute_freq(int v); int get_default_mapID(int ch); void init_channel_layer(int ch); - void get_output(float *buffer, int len); + int compute_data(float *buffer, int32_t count); int send_event(int time, int status, int parm1, int parm2); void send_long_event(int sampletime, const uint8_t *sysexbuffer, int exlen); }; diff --git a/src/sound/timiditypp/resample.cpp b/src/sound/timiditypp/resample.cpp index d7dcb9e9a..90824ed55 100644 --- a/src/sound/timiditypp/resample.cpp +++ b/src/sound/timiditypp/resample.cpp @@ -253,20 +253,9 @@ void initialize_resampler_coeffs(void) initialize_newton_coeffs(); initialize_gauss_table(gauss_n); - /* we don't have to initialize newton table any more */ - /* bounds checking values for the appropriate sample types */ - /* this is as good a place as any to initialize them */ - if (play_mode->encoding & PE_24BIT) - { - sample_bounds_min = -8388608; - sample_bounds_max = 8388607; - } - else /* 16-bit */ - { - sample_bounds_min = -32768; - sample_bounds_max = 32767; - } + sample_bounds_min = -32768; + sample_bounds_max = 32767; } diff --git a/src/sound/timiditypp/timidity.h b/src/sound/timiditypp/timidity.h index d37eca525..75284ea49 100644 --- a/src/sound/timiditypp/timidity.h +++ b/src/sound/timiditypp/timidity.h @@ -29,7 +29,6 @@ #define TIMIDITY_H_INCLUDED 1 #include "c_cvars.h" -#include "output.h" #include "controls.h" #include "mblock.h" diff --git a/src/sound/timiditypp/w32_a.cpp b/src/sound/timiditypp/w32_a.cpp deleted file mode 100644 index dea002c6a..000000000 --- a/src/sound/timiditypp/w32_a.cpp +++ /dev/null @@ -1,670 +0,0 @@ -/* - TiMidity++ -- MIDI to WAVE converter and player - Copyright (C) 1999-2002 Masanao Izumo - Copyright (C) 1995 Tuukka Toivonen - - 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. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - w32_a.c - - Functions to play sound on the Windows audio driver (Windows 95/98/NT). - - Modified by Masanao Izumo -*/ - -#include -#include -#include -#include -#include "timidity.h" - -/*****************************************************************************************************************************/ - - -/*****************************************************************************************************************************/ - -#include "instrum.h" -#include "playmidi.h" -#include "mblock.h" - -namespace TimidityPlus -{ - extern void *safe_malloc(size_t count); - - extern CRITICAL_SECTION critSect; - - static int opt_wmme_device_id = -2; - - UINT uDeviceID; - -#define NOT ! - -static int open_output (void); /* 0=success, 1=warning, -1=fatal error */ -static void close_output (void); -static int output_data (char * Data, int32_t Size); -static int acntl (int request, void * arg); - -static void print_device_list(void); - -#define DATA_BLOCK_SIZE (4 * AUDIO_BUFFER_SIZE) -#define DATA_BLOCK_NUM 8 -static int data_block_trunc_size; - -struct MMBuffer -{ - int Number; - int Prepared; // Non-zero if this buffer has been prepared. - - HGLOBAL hData; - void * Data; - - HGLOBAL hHead; - WAVEHDR * Head; - - struct MMBuffer * Next; -}; - -static struct MMBuffer * Buffers; - -static volatile struct MMBuffer * FreeBuffers; -static volatile int NumBuffersInUse; - -static HWAVEOUT hDevice; -static int BufferDelay; // in milliseconds - -static const int AllowSynchronousWaveforms = 1; - -/*****************************************************************************************************************************/ - -static void CALLBACK OnPlaybackEvent (HWAVE hWave, UINT Msg, DWORD_PTR UserData, DWORD_PTR Param1, DWORD_PTR Param2); -static void BufferPoolReset (void); -static struct MMBuffer * GetBuffer (); -static void PutBuffer (struct MMBuffer *); -static const char * MMErrorMessage (MMRESULT Result); -static void WaitForBuffer (int WaitForAllBuffers); - -/*****************************************************************************************************************************/ - -static int detect(void); - -#define dpm w32_play_mode - -PlayMode dpm = -{ - 44100, - PE_16BIT, - PF_PCM_STREAM|PF_BUFF_FRAGM_OPT, - -1, - {32}, - "Windows audio driver", 'd', - NULL, - open_output, - close_output, - output_data, - acntl, - detect -}; - -/*****************************************************************************************************************************/ -CRITICAL_SECTION critSect; - - -static int open_output(void) -{ - int i; - int j; - int IsMono; - WAVEFORMATEX wf; - WAVEOUTCAPS woc; - MMRESULT Result; - UINT DeviceID; - int ret; - - InitializeCriticalSection(&critSect); - - if( dpm.name != NULL) - ret = sscanf(dpm.name, "%d", &opt_wmme_device_id); - if ( dpm.name == NULL || ret == 0 || ret == EOF) - opt_wmme_device_id = -2; - - if (opt_wmme_device_id == -1){ - print_device_list(); - return -1; - } - -/** Check if there is at least one audio device. **/ - - if (waveOutGetNumDevs() == 0) - { - //ctl_cmsg (CMSG_ERROR, VERB_NORMAL, "No audio devices present!"); - return -1; - } - -/** They can't mean these. **/ - - dpm.encoding = PE_16BIT; - - IsMono = false; - - memset(&wf, 0, sizeof(wf)); - - wf.wFormatTag = WAVE_FORMAT_PCM; - wf.nChannels = 2; - wf.nSamplesPerSec = dpm.rate; - - i = dpm.rate; - j = 4; - i *= j; - data_block_trunc_size = DATA_BLOCK_SIZE - (DATA_BLOCK_SIZE % j); - - wf.nAvgBytesPerSec = i; - wf.nBlockAlign = j; - wf.wBitsPerSample = 16; - wf.cbSize = sizeof(WAVEFORMAT); - -/** Open the device. **/ - - { CHAR b[256]; wsprintf(b, "Opening device...\n"); OutputDebugString(b); } - - hDevice = 0; - - if (opt_wmme_device_id == -2){ - uDeviceID = WAVE_MAPPER; - }else{ - uDeviceID= (UINT)opt_wmme_device_id; - } - - if (AllowSynchronousWaveforms) - Result = waveOutOpen(&hDevice, uDeviceID, (LPWAVEFORMATEX) &wf, (DWORD_PTR) OnPlaybackEvent, 0, CALLBACK_FUNCTION | WAVE_ALLOWSYNC); - else - Result = waveOutOpen(&hDevice, uDeviceID, (LPWAVEFORMATEX) &wf, (DWORD_PTR) OnPlaybackEvent, 0, CALLBACK_FUNCTION); - - if (Result) - { - return -1; - } - else - { CHAR b[256]; wsprintf(b, "Device opened.\n"); OutputDebugString(b); } - -/** Get the device ID. **/ - - DeviceID = 0; - waveOutGetID(hDevice, &DeviceID); - -/** Get the device capabilities. **/ - - memset(&woc, 0, sizeof(WAVEOUTCAPS)); - Result = waveOutGetDevCaps(DeviceID, &woc, sizeof(WAVEOUTCAPS)); - - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Device ID: %d", DeviceID); - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Manufacture ID: %d", woc.wMid); - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Product ID: %d", woc.wPid); - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Driver version: %d", woc.vDriverVersion); - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Product name: %s", woc.szPname); - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Formats supported: 0x%08X", woc.dwFormats); - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Max. channels: %d", woc.wChannels); - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Supported features: 0x%08X", woc.dwSupport); - -/** Calculate the buffer delay. **/ - - BufferDelay = AUDIO_BUFFER_SIZE * 4; - - BufferDelay = (BufferDelay * 1000) / dpm.rate; - -/** Create the buffer pool. **/ - - Buffers = (struct MMBuffer *) safe_malloc(DATA_BLOCK_NUM * sizeof(struct MMBuffer)); - - for (i = 0; i < DATA_BLOCK_NUM; i++) - { - struct MMBuffer * b; - - b = &Buffers[i]; - - b->hData = GlobalAlloc(GMEM_ZEROINIT, DATA_BLOCK_SIZE); - b->Data = (WAVEHDR*)GlobalLock (b->hData); - b->hHead = GlobalAlloc(GMEM_ZEROINIT, sizeof(WAVEHDR)); - b->Head = (WAVEHDR*)GlobalLock (b->hHead); - } - - BufferPoolReset(); - -/** Set the file descriptor. **/ - - dpm.fd = 0; - - return 0; -} - -/*****************************************************************************************************************************/ - -static void close_output(void) -{ - int i; - - if (dpm.fd != -1) - { - WaitForBuffer(1); - - { CHAR b[256]; wsprintf(b, "Closing device...\n"); OutputDebugString(b); } - - waveOutReset(hDevice); - waveOutClose(hDevice); - - { CHAR b[256]; wsprintf(b, "Device closed.\n"); OutputDebugString(b); } - - /** Free all buffers. **/ - - for (i = 0; i < DATA_BLOCK_NUM; i++) - { - struct MMBuffer * block; - - block = &Buffers[i]; - - GlobalUnlock(block->hHead); - GlobalFree (block->hHead); - - GlobalUnlock(block->hData); - GlobalFree (block->hData); - } - - free(Buffers); - - /** Reset the file descriptor. **/ - - dpm.fd = -1; - } -} - -static int detect(void) -{ - if (waveOutGetNumDevs() == 0) {return 0;} /* not found */ - return 1; /* found */ -} - - -/*****************************************************************************************************************************/ - -#ifdef OutputDebugString -#undef OutputDebugString -#endif - -void OutputDebugString(LPSTR sre) -{ -} - -static int output_data(char * Data, int32_t Size) -{ - char * d; - int32_t s; - - d = Data; - s = Size; - - while (s > 0) - { - int32_t n; - struct MMBuffer * b; - - MMRESULT Result; - LPWAVEHDR wh; - - if ((b = GetBuffer()) == NULL) - { - WaitForBuffer(0); - continue; - } - - if (s <= data_block_trunc_size) - n = s; - else - n = data_block_trunc_size; - - CopyMemory(b->Data, d, n); - - wh = b->Head; - - wh->dwBufferLength = n; - wh->lpData = (LPSTR)b->Data; - wh->dwUser = b->Number; - - /** Prepare the buffer. **/ - - { CHAR b[256]; wsprintf(b, "%2d: Preparing buffer %d...\n", NumBuffersInUse, wh->dwUser); OutputDebugString(b); } - - Result = waveOutPrepareHeader(hDevice, wh, sizeof(WAVEHDR)); - - if (Result) - { - { CHAR b[256]; wsprintf(b, "%2d: Buffer preparation failed.\n", NumBuffersInUse); OutputDebugString(b); } - - //ctl_cmsg (CMSG_ERROR, VERB_NORMAL, "waveOutPrepareHeader(): %s", MMErrorMessage(Result)); - return -1; - } - else - { CHAR b[256]; wsprintf(b, "%2d: Buffer %d prepared.\n", NumBuffersInUse, wh->dwUser); OutputDebugString(b); } - - b->Prepared = 1; - - /** Queue the buffer. **/ - - { CHAR b[256]; wsprintf(b, "%2d: Queueing buffer %d...\n", NumBuffersInUse, wh->dwUser); OutputDebugString(b); } - - Result = waveOutWrite(hDevice, wh, sizeof(WAVEHDR)); - - if (Result) - { - { CHAR b[256]; wsprintf(b, "%2d: Buffer queueing failed.\n", NumBuffersInUse); OutputDebugString(b); } - - //ctl_cmsg(CMSG_ERROR, VERB_NORMAL, "waveOutWrite(): %s", MMErrorMessage(Result)); - return -1; - } - else - { CHAR b[256]; wsprintf(b, "%2d: Buffer %d queued.\n", NumBuffersInUse, wh->dwUser); OutputDebugString(b); } - - d += n; - s -= n; - } - - return 0; -} - -/*****************************************************************************************************************************/ - -static int acntl(int request, void *arg) -{ - static char dummy_sounds[4*AUDIO_BUFFER_SIZE]; - - switch(request) - { - case PM_REQ_DISCARD: - { - { CHAR b[256]; wsprintf(b, "Resetting audio device.\n"); OutputDebugString(b); } - - waveOutReset(hDevice); - close_output(); - open_output(); - - { CHAR b[256]; wsprintf(b, "Audio device reset.\n"); OutputDebugString(b); } - - return 0; - } - - case PM_REQ_FLUSH: - { - close_output(); - open_output(); - return 0; - } - } - - return -1; -} - -/*****************************************************************************************************************************/ - -static void CALLBACK OnPlaybackEvent(HWAVE hWave, UINT Msg, DWORD_PTR UserData, DWORD_PTR Param1, DWORD_PTR Param2) -{ - //ctl_cmsg(CMSG_INFO, VERB_DEBUG, "Msg: 0x%08X, Num. buffers in use: %d", Msg, NumBuffersInUse); - - switch (Msg) - { - case WOM_OPEN: - { CHAR b[256]; wsprintf(b, "%2d: Device opened.\n", NumBuffersInUse); OutputDebugString(b); } - break; - - case WOM_CLOSE: - { CHAR b[256]; wsprintf(b, "%2d: Device closed.\n", NumBuffersInUse); OutputDebugString(b); } - break; - - case WOM_DONE: - { - WAVEHDR * wh; - - EnterCriticalSection(&critSect); - - wh = (WAVEHDR *) Param1; - -/* It's not safe to do this here. Read the remarks of waveOutProc() in the SDK on which functions are safe to call. - if (NOT Queueing) - { - { CHAR b[256]; wsprintf(b, "%2d: Dequeueing buffer %d...\n", NumBuffersInUse, wh->dwUser); OutputDebugString(b); } - - waveOutUnprepareHeader(hDevice, wh, sizeof(WAVEHDR)); - - { CHAR b[256]; wsprintf(b, "%2d: Buffer %d dequeued.\n", NumBuffersInUse, wh->dwUser); OutputDebugString(b); } - } - else - { CHAR b[256]; wsprintf(b, "%2d: *** Buffer %d not dequeued! ***\n", NumBuffersInUse, wh->dwUser); OutputDebugString(b); } - */ - PutBuffer(&Buffers[wh->dwUser]); - - LeaveCriticalSection(&critSect); - - break; - } - - default: - { - CHAR b[256]; - - wsprintf(b, "%2d: Unknown play back event 0x%08X.\n", NumBuffersInUse, Msg); - OutputDebugString(b); - } - } -} - -/*****************************************************************************************************************************/ - -#define DIM(a) sizeof(a) / sizeof(a[0]) - -static const char * mmsyserr_code_string[] = -{ - "no error", - "unspecified error", - "device ID out of range", - "driver failed enable", - "device already allocated", - "device handle is invalid", - "no device driver present", - "memory allocation error", - "function isn't supported", - "error value out of range", - "invalid flag passed", - "invalid parameter passed", - "handle being used", -}; - -static const char * waverr_code_sring[] = -{ - "unsupported wave format", - "still something playing", - "header not prepared", - "device is synchronous", -}; - -static const char * MMErrorMessage(MMRESULT ErrorCode) -{ - static char s[32]; - - if (ErrorCode >= WAVERR_BASE) - { - ErrorCode -= WAVERR_BASE; - - if (ErrorCode > DIM(waverr_code_sring)) - { - wsprintf(s, "Unknown wave error %d", ErrorCode); - return s; - } - else - return waverr_code_sring[ErrorCode]; - } - else - if (ErrorCode > DIM(mmsyserr_code_string)) - { - wsprintf(s, "Unknown multimedia error %d", ErrorCode); - return s; - } - else - return mmsyserr_code_string[ErrorCode]; -} - -#undef DIM - -/*****************************************************************************************************************************/ - -static void BufferPoolReset(void) -{ - int i; - - { CHAR b[256]; wsprintf(b, "Resetting buffer pool...\n"); OutputDebugString(b); } - - Buffers[0].Number = 0; - Buffers[0].Prepared = 0; - Buffers[0].Next = &Buffers[1]; - - for (i = 1; i < DATA_BLOCK_NUM - 1; i++) - { - Buffers[i].Number = i; - Buffers[i].Prepared = 0; - Buffers[i].Next = &Buffers[i + 1]; - } - - Buffers[i].Number = i; - Buffers[i].Prepared = 0; - Buffers[i].Next = NULL; - - FreeBuffers = &Buffers[0]; - NumBuffersInUse = 0; - - { CHAR b[256]; wsprintf(b, "Buffer pool reset.\n", NumBuffersInUse); OutputDebugString(b); } -} - -/*****************************************************************************************************************************/ - -static struct MMBuffer * GetBuffer() -{ - struct MMBuffer * b; - - { CHAR b[256]; wsprintf(b, "%2d: Getting buffer...\n", NumBuffersInUse); OutputDebugString(b); } - - EnterCriticalSection(&critSect); - - if (FreeBuffers) - { - b = (struct MMBuffer *)FreeBuffers; - FreeBuffers = FreeBuffers->Next; - NumBuffersInUse++; - - /** If this buffer is still prepared we can safely unprepare it because we got it from the free buffer list. **/ - - if (b->Prepared) - { - waveOutUnprepareHeader(hDevice, (LPWAVEHDR) b->Head, sizeof(WAVEHDR)); - - b->Prepared = 0; - } - - b->Next = NULL; - } - else - b = NULL; - - LeaveCriticalSection(&critSect); - - { CHAR b[256]; wsprintf(b, "%2d: Got buffer.\n", NumBuffersInUse); OutputDebugString(b); } - - return b; -} - -/*****************************************************************************************************************************/ - -static void PutBuffer(struct MMBuffer * b) -{ - { CHAR b[256]; wsprintf(b, "%2d: Putting buffer...\n", NumBuffersInUse); OutputDebugString(b); } - - b->Next = (struct MMBuffer *)FreeBuffers; - FreeBuffers = b; - NumBuffersInUse--; - - { CHAR b[256]; wsprintf(b, "%2d: Buffer put.\n", NumBuffersInUse); OutputDebugString(b); } -} - -/*****************************************************************************************************************************/ - -static void WaitForBuffer(int WaitForAllBuffers) -{ - int numbuf; - - if (WaitForAllBuffers) - { - { CHAR b[256]; wsprintf(b, "%2d: Waiting for all buffers to be dequeued...\n", NumBuffersInUse); OutputDebugString(b); } - - while (1) { - EnterCriticalSection(&critSect); - numbuf = NumBuffersInUse; - if (numbuf) { - LeaveCriticalSection(&critSect); - Sleep(BufferDelay); - continue; - } - break; - } - LeaveCriticalSection(&critSect); - - -// while (NumBuffersInUse) -// Sleep(BufferDelay); - - { CHAR b[256]; wsprintf(b, "%2d: All buffers dequeued.\n", NumBuffersInUse); OutputDebugString(b); } - - BufferPoolReset(); - } - else - { - { CHAR b[256]; wsprintf(b, "%2d: Waiting %dms...\n", NumBuffersInUse, BufferDelay); OutputDebugString(b); } - - Sleep(BufferDelay); - - { CHAR b[256]; wsprintf(b, "%2d: Wait finished.\n", NumBuffersInUse); OutputDebugString(b); } - } -} - -/*****************************************************************************************************************************/ - -#define DEVLIST_MAX 20 -static void print_device_list(void){ - UINT num; - int i, list_num; - WAVEOUTCAPS woc; - typedef struct tag_DEVICELIST{ - int deviceID; - char name[256]; - } DEVICELIST; - DEVICELIST device[DEVLIST_MAX]; - num = waveOutGetNumDevs(); - list_num=0; - for(i = 0 ; i < (int)num && i < DEVLIST_MAX ; i++){ - if (MMSYSERR_NOERROR == waveOutGetDevCaps((UINT)i, &woc, sizeof(woc)) ){ - device[list_num].deviceID=i; - strcpy(device[list_num].name, woc.szPname); - list_num++; - } - } - for(i=0;i