From 919a9593271fb5ec8471bebef90ad5faf541e4a6 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Fri, 8 Mar 2019 02:47:00 +0900 Subject: [PATCH] [VM][EVENT][DEVICE] Add new APIs for recording sound. --- source/src/vm/common_vm/CMakeLists.txt | 2 +- source/src/vm/device.h | 14 +- source/src/vm/event.cpp | 361 ++++++++++++++++++++------------- source/src/vm/event.h | 5 +- source/src/vm/libcpu_newdev/device.cpp | 18 +- source/src/vm/libcpu_newdev/device.h | 4 +- source/src/vm/ym2203.h | 2 +- 7 files changed, 253 insertions(+), 153 deletions(-) diff --git a/source/src/vm/common_vm/CMakeLists.txt b/source/src/vm/common_vm/CMakeLists.txt index 59fa4abf7..89a49b8e8 100644 --- a/source/src/vm/common_vm/CMakeLists.txt +++ b/source/src/vm/common_vm/CMakeLists.txt @@ -1,6 +1,6 @@ message("* vm/common_vm") -SET(THIS_LIB_VERSION 2.8.1) +SET(THIS_LIB_VERSION 2.8.3) #include(cotire) set(s_vm_common_vm_srcs diff --git a/source/src/vm/device.h b/source/src/vm/device.h index 98f7fbdab..371eb8943 100644 --- a/source/src/vm/device.h +++ b/source/src/vm/device.h @@ -129,6 +129,12 @@ public: } return event_manager->is_sound_in_source_exists(bank); } + virtual int increment_sound_in_passed_data(int bank, double passed_usec) { + if(event_manager == NULL) { + return 0; + } + return event_manager->increment_sound_in_passed_data(bank, passed_usec); + } virtual int get_sound_in_buffers_count() { if(event_manager == NULL) { event_manager = vm->first_device->next_device; @@ -167,9 +173,13 @@ public: } // Add sampled values to sample buffer;value may be -32768 to +32767. // this function may be before (or after) initialize(). - virtual int get_sound_in_samples(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels) { + virtual int get_sound_in_latest_data(int bank, int32_t* dst, int expect_channels) { + if(event_manager == NULL) return 0; + return event_manager->get_sound_in_latest_data(bank, dst, expect_channels); + } + virtual int get_sound_in_data(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels) { if(event_manager == NULL) return -1; - return event_manager->get_sound_in_samples(bank, dst, expect_samples, expect_rate, expect_channels); + return event_manager->get_sound_in_data(bank, dst, expect_samples, expect_rate, expect_channels); } virtual void set_high_pass_filter_freq(int freq, double quality) { } // If freq < 0 disable HPF. diff --git a/source/src/vm/event.cpp b/source/src/vm/event.cpp index fa93eef2a..86edbeac5 100644 --- a/source/src/vm/event.cpp +++ b/source/src/vm/event.cpp @@ -947,190 +947,261 @@ int EVENT::write_sound_in_buffer(int bank, int32_t* src, int samples) // ToDo: UnLock Mutex sound_in_writeptr[bank] = sound_in_writeptr[bank] + n_samples; if(sound_in_writeptr[bank] >= sound_in_samples[bank]) sound_in_writeptr[bank] = 0; + sound_in_write_size[bank] += samples; + if(sound_in_write_size[bank] >= sound_in_samples[bank]) sound_in_write_size[bank] = sound_in_samples[bank]; return samples; } // Add sampled values to sample buffer;value may be -32768 to +32767. -int EVENT::get_sound_in_samples(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels) +int EVENT::rechannel_sound_in_data(int32_t*dst, int16_t* src, int dst_channels, int src_channels, int samples) { - if(bank < 0) return -1; - if(bank >= MAX_SOUND_IN_BUFFERS) return -1; - if(sound_in_tmp_buffer[bank] == NULL) return -1; - if(dst == NULL) return -1; - - int n_samples = 0; - int32_t tmpbuf[expect_samples * expect_channels]; - int gave_samples = 0; - int sound_div = 1; - int sound_mod = 0; - if(sound_in_channels[bank] > expect_channels) { - sound_div = sound_in_channels[bank] / expect_channels; - sound_mod = sound_in_channels[bank] % expect_channels; - } else if(sound_in_channels[bank] < expect_channels) { - sound_div = expect_channels / sound_in_channels[bank]; - sound_mod = expect_channels % sound_in_channels[bank]; - } - // ToDo: Lock Mutex - if(sound_in_channels[bank] == expect_channels) { - int32_t* p = tmpbuf; - for(int i = 0; i < expect_samples; i++) { - if(sound_in_write_size[bank] <= 0) break; - int16_t* q = &(sound_in_tmp_buffer[bank][sound_in_readptr[bank] * sound_in_channels[bank]]); - for(int j = 0; j < expect_channels; j++) { - p[j] = q[j]; - - } - sound_in_readptr[bank] = sound_in_readptr[bank] + 1; - if(sound_in_readptr[bank] >= sound_in_samples[bank]) sound_in_readptr[bank] = 0; - n_samples++; - sound_in_write_size[bank] = sound_in_write_size[bank] - 1; + if(dst == NULL) return 0; + if(src == NULL) return 0; + if(dst_channels <= 0) return 0; + if(src_channels <= 0) return 0; + + int cvt_bytes = 0; + memset(dst, 0x00, sizeof(int32_t) * samples * dst_channels); + if(dst_channels == src_channels) { + for(int i = 0; i < (src_channels * samples) ; i++) { + dst[i] = (int32_t)(src[i]); } - } else if(sound_in_channels[bank] > expect_channels) { - for(int i = 0; i < expect_samples; i++) { - int chp = 0; - int chq = 0; - int32_t* p = &(tmpbuf[i * expect_channels]); - int16_t* q = &(sound_in_tmp_buffer[bank][sound_in_readptr[bank] * sound_in_channels[bank]]); - if(sound_in_write_size[bank] <= 0) break; - - for(int j = 0; j < sound_in_channels[bank]; j++) { - *p = *p + q[j]; - chp++; - if(sound_mod == 0) { - if(chp >= sound_div) { - p++; - chp = 0; - chq++; - } - } else { - if((chp >= sound_div) && (chq < (expect_channels - 1))){ - p++; - chp = 0; - chq++; - } - } + } else if(dst_channels < src_channels) { + for(int x = 0; x < samples; x++) { + int mp = 0; + int div_ch = src_channels / dst_channels; + int mod_ch = src_channels % dst_channels; + for(int i = 0; i < dst_channels; i++) { + for(int j = 0; j < div_ch; j++) { + dst[i] = dst[i] + (int32_t)(src[mp]); + mp++; + } } - p = &(dst[i * expect_channels]); - if(sound_mod != 0) { - for(int j = 0; j < (expect_channels - 1); j++) { - *p = *p / sound_div; - p++; + if(mod_ch != 0) { + for(int j = 0; j < mod_ch; j++) { + dst[dst_channels - 1] = dst[dst_channels - 1] + (int32_t)(src[mp]); + mp++; + } + for(int i = 0; i < (dst_channels - 1); i++) { + dst[i] = dst[i] / div_ch; } - *p = *p / (sound_div + sound_mod); + dst[dst_channels - 1] = dst[dst_channels - 1] / (div_ch + mod_ch); } else { - for(int j = 0; j < expect_channels; j++) { - *p = *p / sound_div; - p++; + for(int i = 0; i < dst_channels; i++) { + dst[i] = dst[i] / div_ch; } } - sound_in_readptr[bank] = sound_in_readptr[bank] + 1; - if(sound_in_readptr[bank] >= sound_in_samples[bank]) sound_in_readptr[bank] = 0; - n_samples++; - sound_in_write_size[bank] = sound_in_write_size[bank] - 1; + src = src + src_channels; + dst = dst + dst_channels; } - } else { // sound_in_channels[bank] < expect_channels - int32_t* p = tmpbuf; - for(int i = 0; i < expect_samples; i++) { - if(sound_in_write_size[bank] <= 0) break; - int chp = 0; - int chq = 0; - int16_t* q = &(sound_in_tmp_buffer[bank][sound_in_readptr[bank] * sound_in_channels[bank]]); - for(int j = 0; j < sound_div; j++) { - *p++ = *q; - chp++; - } - if(sound_mod == 0) { - q++; - } else if(chp < (expect_channels - sound_mod - 1)) { - q++; - } else { - for(int j = 0; j < sound_mod; j++) { - *p++ = *q; + } else if(dst_channels > src_channels) { + for(int x = 0; x < samples; x++) { + int mp = 0; + int div_ch = dst_channels / src_channels; + int _n = div_ch; + for(int i = 0; i < dst_channels; i++) { + dst[i] = (int32_t)(src[mp]); + _n--; + if(_n <= 0) { + _n = div_ch; + mp++; + if(mp >= src_channels) { + mp = src_channels - 1; + } } - q++; } - sound_in_readptr[bank] = sound_in_readptr[bank] + 1; - if(sound_in_readptr[bank] >= sound_in_samples[bank]) sound_in_readptr[bank] = 0; - n_samples++; - sound_in_write_size[bank] = sound_in_write_size[bank] - 1; + src = src + src_channels; + dst = dst + dst_channels; } - } + return samples; +} + +int EVENT::increment_sound_in_passed_data(int bank, double passed_usec) +{ + + if(bank < 0) return 0; + if(bank >= MAX_SOUND_IN_BUFFERS) return 0; + if(sound_in_rate[bank] <= 0) return 0; + if(sound_in_samples[bank] <= 0) return 0; + if(passed_usec <= 0.0) return 0; + + double freq = 1.0e6 / sound_in_rate[bank]; + int inc_ptr = (int)(nearbyint(passed_usec / freq)); + int readptr = sound_in_readptr[bank]; + int _ni = inc_ptr; + + if(_ni >= sound_in_samples[bank]) { + _ni = _ni % sound_in_samples[bank]; + } + readptr += _ni; + if(readptr < 0) readptr = 0; + readptr = readptr % sound_in_samples[bank]; + + sound_in_readptr[bank] = readptr; + sound_in_write_size[bank] = sound_in_write_size[bank] - _ni; + if(sound_in_write_size[bank] <= 0) { + sound_in_write_size[bank] = 1; + sound_in_readptr[bank] = sound_in_readptr[bank] - 1; + if(sound_in_readptr[bank] < 0) sound_in_readptr[bank] = sound_in_samples[bank] - 1; + } + return inc_ptr; +} + +int EVENT::get_sound_in_latest_data(int bank, int32_t* dst, int expect_channels) +{ + int gave_samples = 0; + int sound_div = 1; + int sound_mod = 0; + + if(bank < 0) return 0; + if(bank >= MAX_SOUND_IN_BUFFERS) return 0; + if(sound_in_channels[bank] <= 0) return 0; + if(sound_in_rate[bank] <= 0) return 0; + if(sound_in_samples[bank] <= 0) return 0; + if(expect_channels <= 0) return 0; + if(dst == NULL) return 0; + + int readptr = sound_in_writeptr[bank] - 1; + if(readptr < 0) { + readptr = sound_in_samples[bank] - 1; + } + if(readptr >= sound_in_samples[bank]) { + readptr = 0; + } + int16_t tmpbuf[sound_in_channels[bank] + 1]; + int16_t* p = sound_in_tmp_buffer[bank]; + if(p == NULL) return 0; + p =&(p[readptr * sound_in_channels[bank]]); + + for(int i = 0; i < sound_in_channels[bank]; i++) { + tmpbuf[i] = p[i]; + } + + readptr++; + if(readptr >= sound_in_samples[bank]) { + readptr = 0; + } + sound_in_readptr[bank] = readptr; + sound_in_write_size[bank] = 0; + return rechannel_sound_in_data(dst, tmpbuf, expect_channels, sound_in_channels[bank], 1); +} + +int EVENT::get_sound_in_data(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels) +{ + if(bank < 0) return -1; + if(bank >= MAX_SOUND_IN_BUFFERS) return -1; + if(sound_in_tmp_buffer[bank] == NULL) return -1; + if(dst == NULL) return -1; + + int16_t* src = sound_in_tmp_buffer[bank]; + int readptr = sound_in_readptr[bank]; + if(readptr < 0) readptr = 0; + if(readptr >= sound_in_samples[bank]) readptr = 0; + + int gave_samples = 0; + // ToDo: Lock Mutex + int in_count; + in_count = (int)(nearbyint((double)(sound_in_rate[bank]) / (double)expect_rate) * (double)expect_samples); + if(in_count >= sound_in_samples[bank]) in_count = sound_in_samples[bank]; + if(in_count >= sound_in_write_size[bank]) in_count = sound_in_write_size[bank]; + if(in_count <= 0) return 0; + + int16_t tmpbuf_in[(in_count + 1) * sound_in_channels[bank]]; + int32_t tmpbuf[(in_count + 1) * expect_channels] = {0}; + + int mp = 0; + for(int i = 0; i < in_count; i++) { + int tmpr = readptr * sound_in_channels[bank]; + for(int j = 0; j < sound_in_channels[bank]; j++) { + tmpbuf_in[mp] = src[tmpr + j]; + mp++; + } + readptr++; + if(readptr >= sound_in_samples[bank]) readptr = 0; + } + sound_in_readptr[bank] = readptr; + sound_in_write_size[bank] -= in_count; + if(sound_in_write_size[bank] <= 0) sound_in_write_size[bank] = 0; + + gave_samples = rechannel_sound_in_data(tmpbuf, tmpbuf_in, expect_channels, sound_in_channels[bank], in_count); + // ToDo: UnLock Mutex // Got to TMP Buffer if(expect_rate == sound_in_rate[bank]) { int32_t* p = tmpbuf; int32_t* q = dst; - int32_t tval; - for(int i = 0; i < n_samples; i++) { - for(int j = 0; j < expect_channels; j++) { - tval = *q; - tval = tval + *p; - if(tval >= 32768) tval = 32767; - if(tval < -32768) tval = -32768; - *q = tval; - q++; - p++; - } + + for(int i = 0; i < (gave_samples * expect_channels); i++) { + q[i] = p[i]; } - return n_samples; + return gave_samples; } else if(expect_rate > sound_in_rate[bank]) { int32_t* p = tmpbuf; int32_t* q = dst; int32_t tval; + int s_div = expect_rate / sound_in_rate[bank]; + int s_mod = expect_rate % sound_in_rate[bank]; + int mod_count = 0; // ToDo: Interpollate - gave_samples = 0; - for(int i = 0; i < n_samples;) { - for(int j = 0; j < expect_channels; j++) { - tval = *q; - tval = tval + p[j]; - if(tval >= 32768) tval = 32767; - if(tval < -32768) tval = -32768; - *q = tval; - q++; + int n_samples = (int)((double)gave_samples * ((double)expect_rate / (double)sound_in_rate[bank])); + int32_t tmpdata[expect_channels]; + for(int i = 0; i < n_samples; i++) { + for(int ch = 0; ch < expect_channels; ch++) { + tmpdata[ch] = p[ch]; + } + for(int n = 0; n < s_div; n++) { + for(int ch = 0; ch < expect_channels; ch++) { + dst[ch] = tmpdata[ch]; + } + dst = dst + expect_channels; } - sound_in_read_mod[bank] = sound_in_read_mod[bank] + sound_in_rate[bank]; - if(sound_in_read_mod[bank] >= expect_rate) { - sound_in_read_mod[bank] = sound_in_read_mod[bank] - expect_rate; - p = p + expect_channels; - i++; - gave_samples++; + mod_count += s_mod; + if(mod_count >= sound_in_rate[bank]) { + mod_count = mod_count - sound_in_rate[bank]; + for(int ch = 0; ch < expect_channels; ch++) { + q[ch] = tmpdata[ch]; + } + q = q + expect_channels; } + p = p + expect_channels; } - return gave_samples + 1; + return n_samples; } else { // expect_rate < sound_in_rate[bank] + // ToDo: Interpollate int32_t* p = tmpbuf; int32_t* q = dst; int32_t tval; + int s_div = sound_in_rate[bank] / expect_rate; + int s_mod = sound_in_rate[bank] % expect_rate; + int mod_count = 0; + int div_count = s_div; + int s_count = 0; // ToDo: Interpollate - gave_samples = 0; - for(int i = 0; i < n_samples; i++) { - if(i == 0) { - for(int j = 0; j < expect_channels; j++) { - tval = *q; - tval = tval + p[j]; - if(tval >= 32768) tval = 32767; - if(tval < -32768) tval = -32768; - *q = tval; - q++; - } + int n_samples = (int)((double)gave_samples * ((double)expect_rate / (double)sound_in_rate[bank])); + int32_t tmpdata[expect_channels] = {0}; + for(int i = 0; i < gave_samples; i++) { + for(int ch = 0; ch < expect_channels; ch++) { + tmpdata[ch] += p[ch]; } - p = p + expect_channels; - sound_in_read_mod[bank] = sound_in_read_mod[bank] + expect_rate; - if(sound_in_read_mod[bank] >= sound_in_rate[bank]) { - sound_in_read_mod[bank] = sound_in_read_mod[bank] - sound_in_rate[bank]; - for(int j = 0; j < expect_channels; j++) { - tval = *q; - tval = tval + p[j]; - if(tval >= 32768) tval = 32767; - if(tval < -32768) tval = -32768; - *q = tval; - q++; + mod_count += s_mod; + if(mod_count >= expect_rate) { + mod_count = mod_count - expect_rate; + div_count++; + } + div_count--; + s_count++; + if(div_count <= 0) { + div_count = s_div; + for(int ch = 0; ch < expect_channels; ch++) { + q[ch] = tmpdata[ch] / s_count; } - gave_samples++; + s_count = 0; + q = q + expect_channels; } + p = p + expect_channels; } - return gave_samples + 1; + return n_samples; } return 0; } diff --git a/source/src/vm/event.h b/source/src/vm/event.h index e161cfcf9..ea6828fea 100644 --- a/source/src/vm/event.h +++ b/source/src/vm/event.h @@ -347,6 +347,7 @@ public: int release_sound_in_source(int bank); bool is_sound_in_source_exists(int bank); + int increment_sound_in_passed_data(int bank, double passed_usec); int get_sound_in_buffers_count(); int get_sound_in_samples(int bank); int get_sound_in_rate(int bank); @@ -354,7 +355,9 @@ public: int16_t* get_sound_in_buf_ptr(int bank); int write_sound_in_buffer(int bank, int32_t* src, int samples); // Add sampled values to sample buffer;value may be -32768 to +32767. - int get_sound_in_samples(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels); + int get_sound_in_latest_data(int bank, int32_t* dst, int expect_channels); + int get_sound_in_data(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels); + int rechannel_sound_in_data(int32_t*dst, int16_t* src, int dst_channels, int src_channels, int samples); template void set_context_cpu(T* device, uint32_t clocks = CPU_CLOCKS) diff --git a/source/src/vm/libcpu_newdev/device.cpp b/source/src/vm/libcpu_newdev/device.cpp index dc43bd427..0752588e1 100644 --- a/source/src/vm/libcpu_newdev/device.cpp +++ b/source/src/vm/libcpu_newdev/device.cpp @@ -95,6 +95,14 @@ bool DEVICE::is_sound_in_source_exists(int bank) return event_manager->is_sound_in_source_exists(bank); } +int DEVICE::increment_sound_in_passed_data(int bank, double passed_usec) +{ + if(event_manager == NULL) { + return 0; + } + return event_manager->increment_sound_in_passed_data(bank, passed_usec); +} + int DEVICE::get_sound_in_buffers_count() { if(event_manager == NULL) { @@ -144,10 +152,16 @@ int DEVICE::write_sound_in_buffer(int bank, int32_t* src, int samples) // Add sampled values to sample buffer;value may be -32768 to +32767. // this function may be before (or after) initialize(). -int DEVICE::get_sound_in_samples(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels) +int DEVICE::get_sound_in_latest_data(int bank, int32_t* dst, int expect_channels) +{ + if(event_manager == NULL) return 0; + return event_manager->get_sound_in_latest_data(bank, dst, expect_channels); +} + +int DEVICE::get_sound_in_data(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels) { if(event_manager == NULL) return -1; - return event_manager->get_sound_in_samples(bank, dst, expect_samples, expect_rate, expect_channels); + return event_manager->get_sound_in_data(bank, dst, expect_samples, expect_rate, expect_channels); } int DEVICE::get_event_manager_id() diff --git a/source/src/vm/libcpu_newdev/device.h b/source/src/vm/libcpu_newdev/device.h index 212ef5d93..d695a46f6 100644 --- a/source/src/vm/libcpu_newdev/device.h +++ b/source/src/vm/libcpu_newdev/device.h @@ -72,6 +72,7 @@ public: // this function may be before (or after) initialize(). virtual int release_sound_in_source(int bank); virtual bool is_sound_in_source_exists(int bank); + virtual int increment_sound_in_passed_data(int bank, double passed_usec); virtual int get_sound_in_buffers_count(); virtual int get_sound_in_samples(int bank); virtual int get_sound_in_rate(int bank); @@ -82,7 +83,8 @@ public: virtual int write_sound_in_buffer(int bank, int32_t* src, int samples); // Add sampled values to sample buffer;value may be -32768 to +32767. // this function may be before (or after) initialize(). - virtual int get_sound_in_samples(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels); + virtual int get_sound_in_latest_data(int bank, int32_t* dst, int expect_channels); + virtual int get_sound_in_data(int bank, int32_t* dst, int expect_samples, int expect_rate, int expect_channels); virtual void set_high_pass_filter_freq(int freq, double quality) { } // If freq < 0 disable HPF. virtual void set_low_pass_filter_freq(int freq, double quality) { } // If freq <= 0 disable LPF. diff --git a/source/src/vm/ym2203.h b/source/src/vm/ym2203.h index 4d0ac1302..6f4f03f5f 100644 --- a/source/src/vm/ym2203.h +++ b/source/src/vm/ym2203.h @@ -129,7 +129,7 @@ public: uint32_t read_signal(int id); void event_vline(int v, int clock); void event_callback(int event_id, int error); - void mix(int32* buffer, int cnt); + void mix(int32_t* buffer, int cnt); void set_volume(int _ch, int decibel_l, int decibel_r); void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame); // for debugging -- 2.11.0