OSDN Git Service

[VM][EVENT][DEVICE] Add new APIs for recording sound.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Thu, 7 Mar 2019 17:47:00 +0000 (02:47 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Thu, 7 Mar 2019 17:47:00 +0000 (02:47 +0900)
source/src/vm/common_vm/CMakeLists.txt
source/src/vm/device.h
source/src/vm/event.cpp
source/src/vm/event.h
source/src/vm/libcpu_newdev/device.cpp
source/src/vm/libcpu_newdev/device.h
source/src/vm/ym2203.h

index 59fa4ab..89a49b8 100644 (file)
@@ -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
index 98f7fbd..371eb89 100644 (file)
@@ -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.
index fa93eef..86edbea 100644 (file)
@@ -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;
 }
index e161cfc..ea6828f 100644 (file)
@@ -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 <class T>
                void set_context_cpu(T* device, uint32_t clocks = CPU_CLOCKS)
index dc43bd4..0752588 100644 (file)
@@ -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()
index 212ef5d..d695a46 100644 (file)
@@ -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.
        
index 4d0ac13..6f4f03f 100644 (file)
@@ -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