2015-06-01 15 views
14

Tôi muốn tạo ra một giọng nói phát ra hoặc phát ra ánh sáng hoặc một thứ gì đó khi tệp wav phát phát ra âm thanh. Vì vậy, tôi cần phải phát hiện khi một tập tin wav đang nói hoặc khi nó là trong một sự im lặng giữa các từ. Hiện nay tôi đang sử dụng một kịch bản pygame mà tôi đã tìm thấynhận được mức âm thanh wav như đầu ra

import pygame 
pygame.mixer.init() 
pygame.mixer.music.load("my_sentence.wav") 
pygame.mixer.music.play() 
while pygame.mixer.music.get_busy() == True: 
    continue 

Tôi đoán tôi có thể thực hiện một số kiểm tra tại các vòng lặp while để tìm mức độ âm thanh đầu ra, hoặc một cái gì đó như thế, và sau đó gửi nó tới một trong những đầu ra gpio. Nhưng tôi không biết làm thế nào để đạt được điều đó.

Mọi trợ giúp sẽ được đánh giá cao

+0

Đối với tôi, điều này có vẻ như một câu hỏi cho Raspberry Pi SE ... Tôi không biết tại sao nó được di chuyển. – NULL

+0

Nếu tôi hiểu mệnh đề "music.get_busy() == True" while, nó sẽ được thực thi khi tệp .wav đang phát. Vì vậy, bạn sẽ đặt lệnh động cơ của bạn trong vòng lặp trong khi ... phải ... hoặc tôi thiếu một cái gì đó? – NULL

+0

Cảm ơn @NULL vì câu trả lời. 'music.get_busy() == True' sẽ là đúng mọi lúc, vì âm thanh bắt đầu cho đến khi kết thúc. Nhưng tôi muốn phát hiện sự im lặng giữa các từ, tôi không muốn là miệng di chuyển tự động tất cả các thời gian. Tôi muốn ngừng di chuyển trong khi câu trong im lặng. – cor

Trả lời

7

Bạn sẽ cần phải kiểm tra tệp WAV để giải quyết khi có tiếng nói. Cách đơn giản nhất để thực hiện điều này là tìm kiếm các khoảng thời gian lớn và yên tĩnh. Bởi vì âm thanh hoạt động với sóng, khi nó yên lặng các giá trị trong tệp sóng sẽ không thay đổi nhiều, và khi nó lớn thì chúng sẽ thay đổi rất nhiều.

Một cách ước lượng độ ồn là variance. Như bạn có thể thấy bài viết, điều này có thể được định nghĩa là E[(X - mu)^2], có thể được viết average((X - average(X))^2). Ở đây, X là giá trị của tín hiệu tại một điểm nhất định (các giá trị được lưu trữ trong tệp WAV, được gọi là sample trong mã). Nếu nó thay đổi rất nhiều, phương sai sẽ lớn.

Điều này sẽ cho phép bạn tính toán độ ồn của toàn bộ tệp. Tuy nhiên, bạn muốn theo dõi độ lớn của tệp tại bất kỳ thời điểm nào, có nghĩa là bạn cần một hình thức moving average. Một cách dễ dàng để có được điều này là với một first-order low-pass filter.

Tôi chưa thử nghiệm mã bên dưới nên rất khó có thể hoạt động, nhưng nó sẽ giúp bạn bắt đầu. Nó tải tệp WAV, sử dụng các bộ lọc low-pass để theo dõi giá trị trung bình và phương sai, và hoạt động khi phương sai đi trên và dưới một ngưỡng nhất định. Sau đó, trong khi chơi các tập tin WAV nó theo dõi thời gian kể từ khi nó bắt đầu chơi, và in ra cho dù các tập tin WAV là lớn hoặc yên tĩnh.

Đây là những gì bạn vẫn có thể cần phải làm:

  • Fix tất cả các sai lầm cố ý của tôi trong các mã
  • Thêm một cái gì đó hữu ích để phản ứng với/thay đổi yên tĩnh lớn
  • Thay đổi ngưỡng và reaction_time để nhận được kết quả tốt với âm thanh của bạn
  • Thêm một số hysteresis (ngưỡng biến) để dừng ánh sáng nhấp nháy

Tôi hy vọng điều này sẽ hữu ích!

import wave 
import struct 
import time 

def get_loud_times(wav_path, threshold=10000, time_constant=0.1): 
    '''Work out which parts of a WAV file are loud. 
     - threshold: the variance threshold that is considered loud 
     - time_constant: the approximate reaction time in seconds''' 

    wav = wave.open(wav_path, 'r') 
    length = wav.getnframes() 
    samplerate = wav.getframerate() 

    assert wav.getnchannels() == 1, 'wav must be mono' 
    assert wav.getsampwidth() == 2, 'wav must be 16-bit' 

    # Our result will be a list of (time, is_loud) giving the times when 
    # when the audio switches from loud to quiet and back. 
    is_loud = False 
    result = [(0., is_loud)] 

    # The following values track the mean and variance of the signal. 
    # When the variance is large, the audio is loud. 
    mean = 0 
    variance = 0 

    # If alpha is small, mean and variance change slower but are less noisy. 
    alpha = 1/(time_constant * float(sample_rate)) 

    for i in range(length): 
     sample_time = float(i)/samplerate 
     sample = struct.unpack('<h', wav.readframes(1)) 

     # mean is the average value of sample 
     mean = (1-alpha) * mean + alpha * sample 

     # variance is the average value of (sample - mean) ** 2 
     variance = (1-alpha) * variance + alpha * (sample - mean) ** 2 

     # check if we're loud, and record the time if this changes 
     new_is_loud = variance > threshold 
     if is_loud != new_is_loud: 
      result.append((sample_time, new_is_loud)) 
     is_loud = new_is_loud 

    return result 

def play_sentence(wav_path): 
    loud_times = get_loud_times(wav_path) 
    pygame.mixer.music.load(wav_path) 

    start_time = time.time() 
    pygame.mixer.music.play() 

    for (t, is_loud) in loud_times: 
     # wait until the time described by this entry 
     sleep_time = start_time + t - time.time() 
     if sleep_time > 0: 
      time.sleep(sleep_time) 

     # do whatever 
     print 'loud' if is_loud else 'quiet' 
+0

câu trả lời của bạn trông rất tuyệt, tôi sẽ đọc lại và thử mã này vào những ngày tiếp theo. Cảm ơn! ;) – cor

+0

Tôi đã biến nó thành wiki cộng đồng để hy vọng điều đó có nghĩa là bạn có thể chỉnh sửa nó bằng bất kỳ bản sửa lỗi nào bạn tìm thấy. Chúc may mắn! –

Các vấn đề liên quan