Revamp the sample mix to allow for postprocessing on the sample buffer master
authorjweigele <jweigele@local>
Sun, 2 Oct 2022 20:22:43 +0000 (13:22 -0700)
committerjweigele <jweigele@local>
Sun, 2 Oct 2022 20:22:43 +0000 (13:22 -0700)
ffmpegfile.py

index cbe27243e7ca7be432d75fa30ca4792d179b3fa0..2e5db4989b271fd02a518edde80b8768299b88a1 100644 (file)
@@ -127,6 +127,71 @@ class AudioBuffer(discord.AudioSource):
             retval = AudioChunk(b'')
         return retval
 
+
+    def get_sample_chunks(self, buffer_samples):
+        index = 0
+
+        next_samples = buffer_samples[:,index:index+MAX_SAMPLES]
+        while next_samples.size > 0:
+            chunk = AudioChunk(init_samples=next_samples)
+            yield chunk
+            #log.debug(chunk, chunk.samples)
+            # get next chunk
+            index += MAX_SAMPLES
+            next_samples = buffer_samples[:,index:index+MAX_SAMPLES]
+
+    def mix_new_data(self, new_data):
+        try:
+            locked = False
+            buffer_index = 0
+            # init the buffer
+            buffer_array = numpy.zeros(shape=(2,0), dtype='float32')
+            # breaks out when we have a buffer array that's >= the data we want to mix
+            log.debug('Constructing buffer_array')
+            while buffer_array.size < new_data.size:
+                # no more valid samples, create one for mixing
+                if buffer_index >= len(self.samples):
+                    buffer_append = AudioChunk(init_bytes=b'')
+                else:
+                    buffer_append = self.samples[buffer_index]
+                # append to the current array of data
+                # maybe does too much data churn but we'll see
+                buffer_array = numpy.concatenate((buffer_array, buffer_append.samples), axis=1)
+                buffer_index += 1
+            # if we need to pad out the input to match
+            if buffer_array.size != new_data.size:
+                samples_to_add = buffer_array.size - new_data.size
+                new_data = numpy.concatenate((new_data, numpy.repeat(numpy.zeros(shape=(2,1)), samples_to_add//2, axis=1)), axis=1)
+            # actually mix the two buffers now
+            buffer_array = buffer_array + new_data
+            log.debug('Reprocessing here')
+            # would reprocess here
+            board = pedalboard.Pedalboard([
+                                            pedalboard.Gain(gain_db=-3.0)
+                                            ])
+            buffer_array = board(buffer_array, SAMPLE_RATE)
+
+            
+            log.debug('Replacing samples with mixed')
+            locked = self.sample_lock.acquire()
+            for index, chunk in enumerate(self.get_sample_chunks(buffer_array)):
+                # either append if we've run out of runway, or replace if we have old samples
+                if index == len(self.samples):
+                    self.samples.append(chunk)
+                else:
+                    self.samples[index] = chunk
+                
+            log.debug('Done sample mix')
+        except Exception as e:
+            #log.debug('sample size is {} sample_index is {}'.format(self.sample_size, sample_index))
+            traceback.print_exc()
+        finally:
+            if locked:
+                #log.debug('min deck size: {}'.format(min_deck_size))
+                log.debug('releasing lock now')
+                self.sample_lock.release()
+
+
     # get the number of samples in the deck back up to DECK_SIZE
     def fill_deck(self):
         # block if you got nothin
@@ -153,7 +218,6 @@ class AudioBuffer(discord.AudioSource):
     async def process_file(self, filename):
         #rand_str = str(hex(random.randint(0, 10000)))
         #fifo_path = '/tmp/fifo{}'.format(rand_str)
-        locked = False
         try:
             min_deck_size = self.DECK_SIZE
             chunks_to_append = []
@@ -184,50 +248,20 @@ class AudioBuffer(discord.AudioSource):
             shift_tones = random.randint(-10, 10)
             board = pedalboard.Pedalboard([
                                             pedalboard.PitchShift(semitones=shift_tones),
-                                            pedalboard.Gain(gain_db=-3.0)
                                             ])
             buffer_samples = board(buffer_samples, SAMPLE_RATE)
-            index = 0
-            
-            next_samples = buffer_samples[:,index:index+MAX_SAMPLES]
-            while next_samples.size > 0:
-                chunk = AudioChunk(init_samples=next_samples)
-                #log.debug(chunk, chunk.samples)
-                chunks_to_append.append(chunk)
-                # get next chunk
-                index += MAX_SAMPLES
-                next_samples = buffer_samples[:,index:index+MAX_SAMPLES]
 
 
-            # chunk append/insertion (along with mixing)
-            # this is the part that actually needs locked access
-            locked = self.sample_lock.acquire()
-            sample_index = 0
             log.debug('starting the chunk append now')
-            for chunk in chunks_to_append:
-                if self.deck_size < min_deck_size:
-                    min_deck_size = self.deck_size
-
-                if self.sample_size == sample_index:# or True:
-                    #log.debug('appending chunk {} {}'.format(chunk, chunk.samples))
-                    self.samples.append(chunk)
-                # replace
-                else:
-                    #log.debug('mixing chunk {}'.format(chunk))
-                    self.samples[sample_index] = self.samples[sample_index].mix_stream(chunk)
-                sample_index +=1
-            log.debug('finished chunk append final sample_index {} sample_size {}'.format(sample_index, self.sample_size))
+            self.mix_new_data(buffer_samples)
+            #log.debug('finished chunk append final sample_index {} sample_size {}'.format(sample_index, self.sample_size))
+            log.debug('finished chunk append final')
             
 
 
         except Exception as e:
             #log.debug('sample size is {} sample_index is {}'.format(self.sample_size, sample_index))
             traceback.print_exc()
-        finally:
-            if locked:
-                log.debug('min deck size: {}'.format(min_deck_size))
-                self.sample_lock.release()
-            #os.unlink(fifo_path)
 
     def print_buffer(self):
         for sample in self.samples: