Воспроизвести несколько зацикленных звуковых дорожек, начиная с произвольного времени в Python? - PullRequest
1 голос
/ 19 марта 2019

У меня есть список звуковых образцов различной длины, сохраненных в виде файлов .wav. Я хочу сыграть семпл кулака и сделать его зацикленным навсегда. Как некоторый момент времени после события или изменения состояния, я хочу, чтобы 2-й семпл начал играть с первого семпла. Тогда оба сэмпла будут зациклены навсегда.

После следующего события третий образец будет добавлен в микс. Все три сэмпла будут зациклены навсегда. Это будет продолжаться для всех образцов.

Я успешно воспроизвел несколько дорожек одновременно, но не смог добавить новую дорожку к ранее записанной дорожке. Я пытался с PyAudio и PyDub.

Есть ли способ создать непрерывный зацикленный поток, в который добавляются дополнительные дорожки? Я немного застрял. Заранее спасибо.

from pydub import AudioSegment
from pydub.playback import play

audio1 = AudioSegment.from_file("zipper.wav") 
audio2 = AudioSegment.from_file("jar.wav") 
audio3 = AudioSegment.from_file("dribble.wav") 

mixed = audio1.overlay(audio2)          
mixed1  = mixed.overlay(audio3)

mixed1.export("mixed.wav", format='wav')

play(mixed1)   

РЕДАКТИРОВАТЬ # 1

Продолжая экспериментировать, кажется, что pydub - это функция блокировки, поэтому я не смогу ее использовать, поскольку буду совмещать это микширование звука с анализом тепловизионной камеры с помощью OpenCV и светодиодной матрицы света.

Не уверен, куда идти отсюда.

Редактировать # 2 По этой ссылке я нашел некоторый неблокирующий код pyaudio. Это позволяет мне воспроизводить один файл .wav по бесконечному циклу. Я пытался добавить второго игрока, но он выдал ошибку.

Код для неблокирующего зацикливания .wav

import os
import time
import wave
import threading
import sys

# PyAudio Library
import pyaudio

class WavePlayerLoop(threading.Thread) :
  """
  A simple class based on PyAudio to play wave loop.
  It's a threading class. You can play audio while your application
  continues to do its stuff. :)
  """

  CHUNK = 1024

  def __init__(self,filepath,loop=True) :
    """
    Initialize `WavePlayerLoop` class.
    PARAM:
        -- filepath (String) : File Path to wave file.
        -- loop (boolean)    : True if you want loop playback. 
                               False otherwise.
    """
    super(WavePlayerLoop, self).__init__()
    self.filepath = os.path.abspath(filepath)
    self.loop = loop

  def run(self):
    # Open Wave File and start play!
    wf = wave.open(self.filepath, 'rb')
    player = pyaudio.PyAudio()

    # Open Output Stream (basen on PyAudio tutorial)
    stream = player.open(format = player.get_format_from_width(wf.getsampwidth()),
        channels = wf.getnchannels(),
        rate = wf.getframerate(),
        output = True)

    # PLAYBACK LOOP
    data = wf.readframes(self.CHUNK)
    while self.loop :
      stream.write(data)
      data = wf.readframes(self.CHUNK)
      if data == b'' : # If file is over then rewind.
        wf.rewind()
        data = wf.readframes(self.CHUNK)

    stream.close()
    player.terminate()


  def play(self) :
    """
    Just another name for self.start()
    """
    self.start()

  def stop(self) :
    """
    Stop playback. 
    """
    self.loop = False


player = WavePlayerLoop("zipper.wav", loop=True)
player.play()

Кроме того, если я поместил вызов функции в некоторое время true: loop, то ничего не произойдет. Не знаю почему.

 # Main program logic follows:
    try:

        while True:
            player = WavePlayerLoop("zipper.wav", loop=True)
            player.play()
    except KeyboardInterrupt:
        player.terminate()

1 Ответ

0 голосов
/ 20 марта 2019

После копания и многочисленных попыток я нашел способ сделать это с помощью модуля pygame.Изначально я не исследовал этот модуль, потому что думал, что он ограничен 8 одновременными звуками.Это просто настройка по умолчанию.

pygame.mixer.set_num_channels(26)

Я изменил количество каналов на 26.

import pygame
import time

pygame.mixer.init()
pygame.init()

pygame.mixer.set_num_channels(26)

sound1 = pygame.mixer.Sound("sound1.ogg")
sound2 = pygame.mixer.Sound("sound2.ogg")

sound1.play(loops = -1)
time.sleep (2)

sound2.play(loop = -1)
...