2016-04-04 5 views
1

Я пытаюсь записать аудио и одновременно распечатать амплитуду записанного сигнала. Поэтому я сохраняю все данные в stream.read. Но когда я пытаюсь их распечатать, у меня есть строка байтов и целых чисел. Я хотел бы знать, как преобразовать эти знаки, чтобы получить амплитуду.PyAudio - конвертировать stream.read в int для получения амплитуды

Это мой код:

import pyaudio 
import wave 

CHUNK = 1024 
FORMAT = pyaudio.paInt16 
CHANNELS = 1 
RATE = 44100 
RECORD_SECONDS = 5 
WAVE_OUTPUT_FILENAME = "output.wav" 

p = pyaudio.PyAudio() 

stream = p.open(format=FORMAT, 
       channels=CHANNELS, 
       rate=RATE, 
       input=True, 
       frames_per_buffer=CHUNK) 

print("* recording") 

frames = [] 

for i in range(0, int(RATE/CHUNK * RECORD_SECONDS)): 
    data = stream.read(CHUNK) 
    frames.append(data) # 2 bytes(16 bits) per channel 

print("* done recording") 

stream.stop_stream() 
stream.close() 
p.terminate() 

for data in frames: 
    print(data) 

И это то, что я получаю:

 ����# ���� 
      
!$ 
      

       �� ���� �������������������������� 
      ������ �� ��           
�� 

    �� ������ ���������������������������� 
          ��  
            ����             

% () , . % #

ответ

1

Вы, безусловно, можете вдохновить себя следующий код:

#!/usr/bin/python 

# open a microphone in pyAudio and listen for taps 

import pyaudio 
import struct 
import math 

INITIAL_TAP_THRESHOLD = 0.010 
FORMAT = pyaudio.paInt16 
SHORT_NORMALIZE = (1.0/32768.0) 
CHANNELS = 2 
RATE = 44100 
INPUT_BLOCK_TIME = 0.05 
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME) 
# if we get this many noisy blocks in a row, increase the threshold 
OVERSENSITIVE = 15.0/INPUT_BLOCK_TIME      
# if we get this many quiet blocks in a row, decrease the threshold 
UNDERSENSITIVE = 120.0/INPUT_BLOCK_TIME 
# if the noise was longer than this many blocks, it's not a 'tap' 
MAX_TAP_BLOCKS = 0.15/INPUT_BLOCK_TIME 

def get_rms(block): 
    # RMS amplitude is defined as the square root of the 
    # mean over time of the square of the amplitude. 
    # so we need to convert this string of bytes into 
    # a string of 16-bit samples... 

# we will get one short out for each 
# two chars in the string. 
count = len(block)/2 
format = "%dh"%(count) 
shorts = struct.unpack(format, block) 

# iterate over the block. 
    sum_squares = 0.0 
    for sample in shorts: 
     # sample is a signed short in +/- 32768. 
     # normalize it to 1.0 
     n = sample * SHORT_NORMALIZE 
     sum_squares += n*n 

    return math.sqrt(sum_squares/count) 

class TapTester(object): 
    def __init__(self): 
     self.pa = pyaudio.PyAudio() 
     self.stream = self.open_mic_stream() 
     self.tap_threshold = INITIAL_TAP_THRESHOLD 
     self.noisycount = MAX_TAP_BLOCKS+1 
     self.quietcount = 0 
     self.errorcount = 0 

    def stop(self): 
     self.stream.close() 

    def find_input_device(self): 
     device_index = None    
     for i in range(self.pa.get_device_count()):  
      devinfo = self.pa.get_device_info_by_index(i) 
      print("Device %d: %s"%(i,devinfo["name"])) 

      for keyword in ["mic","input"]: 
       if keyword in devinfo["name"].lower(): 
        print("Found an input: device %d - %s"%  (i,devinfo["name"])) 
        device_index = i 
        return device_index 

    if device_index == None: 
     print("No preferred input found; using default input device.") 

    return device_index 

def open_mic_stream(self): 
    device_index = self.find_input_device() 

    stream = self.pa.open( format = FORMAT, 
          channels = CHANNELS, 
          rate = RATE, 
          input = True, 
          input_device_index = device_index, 
          frames_per_buffer = INPUT_FRAMES_PER_BLOCK) 

    return stream 

def tapDetected(self): 
    print "Tap!" 

def listen(self): 
    try: 
     block = self.stream.read(INPUT_FRAMES_PER_BLOCK) 
    except IOError, e: 
     # dammit. 
     self.errorcount += 1 
     print("(%d) Error recording: %s"%(self.errorcount,e)) 
     self.noisycount = 1 
     return 

    amplitude = get_rms(block) 
    if amplitude > self.tap_threshold: 
     # noisy block 
     self.quietcount = 0 
     self.noisycount += 1 
     if self.noisycount > OVERSENSITIVE: 
      # turn down the sensitivity 
      self.tap_threshold *= 1.1 
    else:    
     # quiet block. 

     if 1 <= self.noisycount <= MAX_TAP_BLOCKS: 
      self.tapDetected() 
     self.noisycount = 0 
     self.quietcount += 1 
     if self.quietcount > UNDERSENSITIVE: 
      # turn up the sensitivity 
      self.tap_threshold *= 0.9 

if __name__ == "__main__": 
tt = TapTester() 

for i in range(1000): 
    tt.listen() 

Он пришел с этим поста : [Detect tap with pyaudio from live mic

Вы можете легко адаптировать его, чтобы поместить RMS в таблицу и построить таблицу.

+0

Спасибо за ваш ответ. Я просто добавил класс get_rms и сохранил значения в списке, и все в порядке. Я получаю список амплитуд, которые увеличиваются или уменьшаются независимо от того, говорю я или нет. – Utopia

+0

Ницца. Теперь, если вы действительно хотите построить сюжет, я предлагаю вам использовать pyqt. – FLCcrakers

0

PyAudio предоставляет вам двоично-кодированные аудиокадры в виде байтов в строка. Смотрите ответ на этот вопрос для того, как напечатать читаемое представление ваших кадров:

Get an audio sample as float number from pyaudio-stream

+0

Спасибо за ваш ответ. Я просто добавляю строку «decoded = numpy.fromstring (данные,« Float32 »); в моем цикле for, но результат не завершается. Я получил список очень маленьких чисел, таких как: 3.67348991e-40 6.42851276e-40 3.67355998e-40 6.42868091e-40 2.75502285e-40 1.10201895e-39 nan 4.59204105e-40e-40 1.19389508e-39 1.37756747e-39 – Utopia

+0

Вам необходимо использовать правильный формат для ваших данных. try 'decoded = numpy.fromstring (data, dtype = numpy.int16)'. Я предлагаю 'numpy.int16', поскольку вы, похоже, определили поток как состоящий из 16-битных целых выборок. Если вы хотите попробовать разные форматы, вот список тех, которые поддерживаются numpy: http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.dtype.html#numpy .dtype – NoThatIsTeal

0

Я думаю, что вы могли бы сделать это

data = stream.read(CHUNK) 
for each in data: 
    print(each)