def fx_distortion(chunk_p, gain_p, tres_p): if len(chunk_p) != 2 * CHUNK: print('[distortion] chunk size is not %d but %d' % (2 * CHUNK, len(chunk_p))) return chunk_p if tres_p<= 0: print('[distortion] threshold should be > 0!') return chunk_p if tres_p > 1: print('[distortion] threshold should be < 1!') return chunk_p if gain_p < 1: print('[distortion] gain should be > 1!') return chunk_p #do distortion temp1 = audioop.mul(chunk_p, 2, 1 / tres_p) temp2 = audioop.mul(temp1, 2, tres_p) #do gain chunk_p = audioop.mul(temp2, 2, gain_p) del temp1 del temp2 return chunk_p
def mul_stereo(fileName,width,lfactor,rfactor): lsample = audioop.tomono(fileName, width, 1, 0) rsample = audioop.tomono(fileName,width, 0, 1) lsample = audioop.mul(lsample,width,lfactor) rsample = audioop.mul(rsample, width,rfactor) lsample = audioop.tostereo(lsample, width, 1, 0) rsample = audioop.tostereo(rsample, width, 0, 1) return audioop.add(lsample,rsample,width)
def test_mul(self): data2 = [] for d in data: str = '' for s in d: str = str + chr(ord(s)*2) data2.append(str) self.assertEqual(audioop.mul(data[0], 1, 2), data2[0]) self.assertEqual(audioop.mul(data[1],2, 2), data2[1]) self.assertEqual(audioop.mul(data[2], 4, 2), data2[2])
def test_mul(self): data2 = [] for d in data: str = bytearray(len(d)) for i,b in enumerate(d): str[i] = 2*b data2.append(str) self.assertEqual(audioop.mul(data[0], 1, 2), data2[0]) self.assertEqual(audioop.mul(data[1],2, 2), data2[1]) self.assertEqual(audioop.mul(data[2], 4, 2), data2[2])
def convert_wave_data(f_rate,frame_count,sample_width,channels,data): """ Convert wave sample data into pleo format """ if channels==2: data = audioop.tomono(data,sample_width,1,1) data = audioop.mul(data,sample_width,0.97999999999999998) data = audioop.ratecv(data,sample_width,1,f_rate,11025,None,4,4)[0] if sample_width==1: data = audioop.bias(data,1,-128) data = audioop.lin2lin(data,1,2) data = audioop.mul(data,2,(1.0/256)) data = audioop.lin2adpcm(data,2,None)[0] return (11025,frame_count,sample_width,1,data)
def testmul(data): data2 = [] for d in data: str = '' for s in d: str = str + chr(ord(s)*2) data2.append(str) if audioop.mul(data[0], 1, 2) <> data2[0] or \ audioop.mul(data[1],2, 2) <> data2[1] or \ audioop.mul(data[2], 4, 2) <> data2[2]: return 0 return 1
def _play(self, start, length): self.isplaying = True if AudioSegment: millisecondchunk = 50 / 1000.0 playchunk = self.pydubfile[start*1000.0:(start+length)*1000.0] - (60 - (60 * (self.volume/100.0))) self.time = start self.audio.play(playchunk.get_array_of_samples(), blocking=False) # For some reason it does not like the seperated chunks, so we play it non- # We might be able to use self.audio.get_stream().time to improve accuracy for chunks in make_chunks(playchunk, millisecondchunk*1000): self.time += millisecondchunk time.sleep(millisecondchunk) if not self.isplaying: break if self.time >= start+length: break else: startframe = int(round(start * self.wave_reference.getframerate())) samplelen = int(round(length * self.wave_reference.getframerate())) remaining = samplelen chunk = 1024 try: self.wave_reference.setpos(startframe) except wave.Error: self.isplaying = False return if remaining >= 1024: data = audioop.mul(self.wave_reference.readframes(chunk),self.wave_reference.getsampwidth(), self.volume/100.0) remaining -= chunk else: data = audioop.mul(self.wave_reference.readframes(remaining),self.wave_reference.getsampwidth(), self.volume/100.0) remaining = 0 # play stream self.audio.play(data.get_array_of_samples(), blocking=False) while len(data) > 0 and self.isplaying: time.sleep(float(self.wave_reference.getframerate())) self.time = float(self.wave_reference.tell()) / float(self.wave_reference.getframerate()) if remaining >= 1024: data = audioop.mul(self.wave_reference.readframes(chunk),self.wave_reference.getsampwidth(), self.volume/100.0) remaining -= chunk else: data = audioop.mul(self.wave_reference.readframes(remaining),self.wave_reference.getsampwidth(), self.volume/100.0) remaining = 0 self.audio.stop() self.isplaying = False
def testmul(data): if verbose: print 'mul' data2 = [] for d in data: str = '' for s in d: str = str + chr(ord(s)*2) data2.append(str) if audioop.mul(data[0], 1, 2) != data2[0] or \ audioop.mul(data[1],2, 2) != data2[1] or \ audioop.mul(data[2], 4, 2) != data2[2]: return 0 return 1
def mix(layers, leftalign=True, boost=2.0): """ mixes N stereo audio strings """ attenuation = 1.0 / len(layers) attenuation *= boost layers.sort(key = len) output_length = flen(layers[-1]) out = pad('', output_length, 0) for layer in layers: padding = output_length - flen(layer) if leftalign: layer = pad(layer, 0, padding) else: layer = pad(layer, padding, 0) layer = audioop.mul(layer, audio_params[1], attenuation) if len(layer) != ftc(output_length) or len(out) != ftc(output_length): dif = int(math.fabs(len(layer) - len(out))) log('unequal'+str(dif)) if len(out) < len(layer): layer = layer[:len(layer) - dif] else: out = out[:len(out) - dif] out = audioop.add(out, layer, audio_params[1]) return out
def get_flush(st, channels, fade=0): """Like soundtouch's flush, don't require that all data comes through, just any. If fade > 0, only allow [fade] samples, and linearly scale volume to 0 over that length""" waiting = st.waiting_count() ready = st.ready_count() result = "" silence = array('h', [0] * 64) while st.ready_count() == ready: st.put_samples(silence) while st.ready_count() > 0: result += st.get_samples(11025) st.clear() if len(result) > 2 * channels * waiting: result = result[0:(2 * channels * waiting)] fade = min(fade, len(result) / 2) if fade > 0: resultstring = "" for ii in xrange(fade / channels): i0 = ii * 2*channels i1 = (ii+1) * 2*channels resultstring += audioop.mul(result[i0:i1], 2, 1 - float(ii) / (fade / channels)) result = resultstring return result
def __getitem__(self, millisecond): if isinstance(millisecond, slice): start = millisecond.start if millisecond.start is not None else 0 end = millisecond.stop if millisecond.stop is not None \ else len(self) start = min(start, len(self)) end = min(end, len(self)) else: start = millisecond end = millisecond + 1 start = self._parse_position(start) * self.frame_width end = self._parse_position(end) * self.frame_width data = self._data[start:end] # ensure the output is as long as the requester is expecting expected_length = end - start missing_frames = (expected_length - len(data)) / self.frame_width if missing_frames: if missing_frames > self.frame_count(ms=2): raise TooManyMissingFrames("You should never be filling in "\ " more than 2 ms with silence here, missing frames: %s" % \ missing_frames) silence = audioop.mul(data[:self.frame_width], self.sample_width, 0) data += (silence * missing_frames) return self._spawn(data)
def _do_run(self): self.loops = 0 self._start = time.time() while not self._end.is_set(): # are we paused? if not self._resumed.is_set(): # wait until we aren't self._resumed.wait() if not self._connected.is_set(): self.stop() break self.loops += 1 data = self.buff.read(self.frame_size) if self._volume != 1.0: data = audioop.mul(data, 2, min(self._volume, 2.0)) if len(data) != self.frame_size: self.stop() break self.player(data) next_time = self._start + self.delay * self.loops delay = max(0, self.delay + (next_time - time.time())) time.sleep(delay)
def tick(self): self.effect.tick() if self.period == 0 or self.sample is None: return dummy_sample else: data = self.sample.get_data(self.sample_offset, self.samples_per_tick()) self.sample_offset += self.samples_per_tick() return mul(data, 1, self.volume / 64.0)
def fx_noise_cancel(chunk_p, tres_p): if len(chunk_p) != 2 * CHUNK: print('[echo] chunk size is not %d but %d' % (2 * CHUNK, len(chunk_p))) return chunk_p power = audioop.rms(chunk_p, 2) / float(math.pow(2, 15)) if power < tres_p: chunk_p = audioop.mul(chunk_p, 2, 0) return chunk_p
def mul(self, factor): """ Return frames for which all samples are multiplied by factor. Samples are truncated in case of overflow. :param factor: (int) the factor which will be applied to each sample. :returns: (str) converted frames """ return audioop.mul(self._frames, self._sampwidth, factor)
def echocancel(outputdata, inputdata): pos = audioop.findmax(outputdata, 800) # one tenth second out_test = outputdata[pos*2:] in_test = inputdata[pos*2:] ipos, factor = audioop.findfit(in_test,out_test) prefill = '\0'*(pos+ipos)*2 postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata)) outputdata = prefill + audioop.mul(outputdata,2-factor) + postfill return audioop.add(inputdata, outputdata,2)
def amplify_max(self): """Amplify the sample to maximum volume without clipping or overflow happening.""" assert not self.__locked max_amp = audioop.max(self.__frames, self.samplewidth) max_target = 2 ** (8 * self.samplewidth - 1) - 2 if max_amp > 0: factor = max_target/max_amp self.__frames = audioop.mul(self.__frames, self.samplewidth, factor) return self
def __mul__(self, factor): """ Implement audio_data * factor """ if not isinstance(factor, (int, float)): return NotImplemented # passing the job to factor.__rmul__ new_byte_data = audioop.mul(self.BYTE_DATA, self.BIT_WIDTH, factor) return type(self)(new_byte_data, self.SAMPLE_RATE, self.BIT_WIDTH, self.CHANNELS, self.dtype)
def test_mul(self): for w in 1, 2, 3, 4: self.assertEqual(audioop.mul(b"", w, 2), b"") self.assertEqual(audioop.mul(bytearray(), w, 2), b"") self.assertEqual(audioop.mul(memoryview(b""), w, 2), b"") self.assertEqual(audioop.mul(datas[w], w, 0), b"\0" * len(datas[w])) self.assertEqual(audioop.mul(datas[w], w, 1), datas[w]) self.assertEqual(audioop.mul(datas[1], 1, 2), b"\x00\x24\x7f\x80\x7f\x80\xfe") self.assertEqual(audioop.mul(datas[2], 2, 2), packs[2](0, 0x2468, 0x7FFF, -0x8000, 0x7FFF, -0x8000, -2)) self.assertEqual( audioop.mul(datas[3], 3, 2), packs[3](0, 0x2468AC, 0x7FFFFF, -0x800000, 0x7FFFFF, -0x800000, -2) ) self.assertEqual( audioop.mul(datas[4], 4, 2), packs[4](0, 0x2468ACF0, 0x7FFFFFFF, -0x80000000, 0x7FFFFFFF, -0x80000000, -2) )
def get_32bit_frames(self, scale_amplitude=True): """Returns the raw sample frames scaled to 32 bits. See make_32bit method for more info.""" if self.samplewidth == 4: return self.__frames frames = audioop.lin2lin(self.__frames, self.samplewidth, 4) if not scale_amplitude: # we need to scale back the sample amplitude to fit back into 24/16/8 bit range factor = 1.0/2**(8*abs(self.samplewidth-4)) frames = audioop.mul(frames, 4, factor) return frames
def mul(self, factor): """ Return frames that has all samples are multiplied by factor. Samples are truncated in case of overflow. @param factor (int) the factor which will be applied to each sample. @return converted frames """ return audioop.mul(self.frames, self.sampwidth, factor)
def mul(fragment, sampwidth, factor): """ Return a fragment that has all samples in the original fragment multiplied by the floating-point value factor. Samples are truncated in case of overflow. @param fragment (string) input frames. @param sampwidth (int) sample width of the frames. @param factor (int) the factor which will be applied to each sample. @return converted frames """ return audioop.mul(fragment, sampwidth, factor)
def _frame_vol(self, frame, mult, *, maxv=2, use_audioop=True): if use_audioop: return audioop.mul(frame, 2, min(mult, maxv)) else: # ffmpeg returns s16le pcm frames. frame_array = array('h', frame) for i in range(len(frame_array)): frame_array[i] = int(frame_array[i] * min(mult, min(1, maxv))) return frame_array.tobytes()
def pan(slice, pan_pos=0.5, amp=1.0): amps = pantamp(pan_pos) lslice = audioop.tomono(slice, audio_params[1], 1, 0) lslice = audioop.tostereo(lslice, audio_params[1], amps[0], 0) rslice = audioop.tomono(slice, audio_params[1], 0, 1) rslice = audioop.tostereo(rslice, audio_params[1], 0, amps[1]) slice = audioop.add(lslice, rslice, audio_params[1]) return audioop.mul(slice, audio_params[1], amp)
def env(audio_string, wavetable_type="sine", fullres=False, highval=1.0, lowval=0.0): # Very short envelopes are possible... if flen(audio_string) < dsp_grain * 4 or fullres == True: packets = split(audio_string, 1) else: packets = split(audio_string, dsp_grain) wtable = wavetable(wavetable_type, len(packets), highval, lowval) packets = [audioop.mul(packet, audio_params[1], wtable[i]) for i, packet in enumerate(packets)] return ''.join(packets)
def echocancel(outputdata, inputdata): """Try to identify an echo and remove it. Should contain 2-byte samples""" pos = audioop.findmax(outputdata, 800) out_test = outputdata[pos*2:] in_test = inputdata[pos*2:] ipos, factor = audioop.findfit(in_test, out_test) factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)], out_test) prefill = '\0'*(pos+ipos)*2 postfill = '\0'*(len(inputdata) - len(prefill) - len(outputdata)) outputdata = prefill + audioop.mul(outputdata, 2, -factor) + postfill return audioop.add(inputdata, outputdata, 2)
def test_mul(self): for w in 1, 2, 3, 4: self.assertEqual(audioop.mul(b'', w, 2), b'') self.assertEqual(audioop.mul(bytearray(), w, 2), b'') self.assertEqual(audioop.mul(memoryview(b''), w, 2), b'') self.assertEqual(audioop.mul(datas[w], w, 0), b'\0' * len(datas[w])) self.assertEqual(audioop.mul(datas[w], w, 1), datas[w]) self.assertEqual(audioop.mul(datas[1], 1, 2), b'\x00\x24\x7f\x80\x7f\x80\xfe') self.assertEqual(audioop.mul(datas[2], 2, 2), packs[2](0, 0x2468, 0x7fff, -0x8000, 0x7fff, -0x8000, -2)) self.assertEqual(audioop.mul(datas[3], 3, 2), packs[3](0, 0x2468ac, 0x7fffff, -0x800000, 0x7fffff, -0x800000, -2)) self.assertEqual(audioop.mul(datas[4], 4, 2), packs[4](0, 0x2468acf0, 0x7fffffff, -0x80000000, 0x7fffffff, -0x80000000, -2))
def raw_read(self): """Return some amount of data as a raw audio string""" buf = self.source.raw_read() if buf is None: self.eof = True return None # Perform the scaling and biasing if self.scale != 1.0: buf = audioop.mul(buf, self.source.raw_width(), self.scale) if self.bias != 0: buf = audioop.bias(buf, self.source.raw_width(), self.bias) return buf
def mixAudio(self): # XXX see the comment above about storing a decaying number for the # volume. For instance, each time round the loop, take the calculated # volume, and the stored volume, and do something like: # newStoredVolume = (oldStoredVolume * 0.33) + (thisPacketVolume * 0.66) import audioop self._audioOut = {} if not self._open: log.msg('mixing closed room %r'%(self,), system='doug') return audioIn = {} for m in self._members: bytes = m.getAudioForRoom() if bytes: audioIn[m] = bytes if CONFDEBUG: print "room %r has %d members"%(self, len(self._members)) print "got %d samples this time"%len(audioIn) print "samples: %r"%(audioIn.items(),) # short-circuit this case if len(self._members) < 2: if CONFDEBUG: print "less than 2 members, no sound" self._audioOutDefault = '' return # Samples is (confsource, audio) samples = audioIn.items() # power is three-tuples of (rms,audio,confsource) power = [ (audioop.rms(x[1],2),x[1], x[0]) for x in samples ] power.sort(); power.reverse() if CONFDEBUG: for rms,audio,confsource in power: print confsource, rms # Speakers is a list of the _maxSpeakers loudest speakers speakers = Set([x[2] for x in power[:self._maxSpeakers]]) # First we calculate the 'default' audio. Used for everyone who's # not a speaker in the room. samples = [ x[1] for x in power[:self._maxSpeakers] ] scaledsamples = [ audioop.mul(x, 2, 1.0/len(samples)) for x in samples ] if scaledsamples: # ooo. a use of reduce. first time for everything... try: combined = reduce(lambda x,y: audioop.add(x, y, 2), scaledsamples) except audioop.error, exc: # XXX tofix! print "combine got error %s"%(exc,) print "lengths", [len(x) for x in scaledsamples] combined = ''
def run(self): while 1: olddata = data = self.iport.readsamps(600) if self.do_ulaw: data = audioop.lin2ulaw(data, 2) data = audioop.ulaw2lin(data, 2) if self.do_adpcm: data, nacstate = audioop.lin2adpcm(data, 2, \ self.acstate) data, dummy = audioop.adpcm2lin(data, 2, \ self.acstate) self.acstate = nacstate if self.do_diff: olddata = audioop.mul(olddata, 2, -1) data = audioop.add(olddata, data, 2) self.oport.writesamps(data) fl.check_forms()