2015-12-30 10 views
6

पर बहुत सारे ध्वनि बजाना मैं पाइथन में एक प्रोग्राम बनाने का प्रयास कर रहा हूं जो एक निश्चित कुंजी दबाए जाने पर एक विशेष harpsichord नोट निभाता है। मैं इसे उत्तरदायी बना देना चाहता हूं ताकि आप अधिक नोट्स (सामान्य इलेक्ट्रिक पियानो की तरह) खेलना जारी रख सकें। हालांकि, क्योंकि WAV फ़ाइलें जो नोट्स संग्रहीत हैं, लगभग 7-10 सेकंड लंबी हैं, मुझे कुछ समस्याएं आ रही हैं। मैं प्रति सेकेंड कम से कम 10 कुंजी दबा सकता हूं। तो, एक नोट की अवधि में मेरे पास एक बार में लगभग 100 अलग-अलग WAV फ़ाइलें चल सकती थीं। मैंने winsound का उपयोग करने की कोशिश की, लेकिन यह एक साथ कई wav फ़ाइलों को चलाने में असमर्थ था। मैं फिर PyAudio पर चले गए और यह तरह काम करता है।एक बार

from msvcrt import getch 
import pyaudio 
import wave 
import multiprocessing as mp 

#This function is just code for playing a sound in PyAudio 
def playNote(filename): 

    CHUNK = 1024 

    wf = wave.open(filename, 'rb') 


    p = pyaudio.PyAudio() 

    stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), 
        channels=wf.getnchannels(), 
        rate=wf.getframerate(), 
        output=True) 

    data = wf.readframes(CHUNK) 

    while data != '': 
     stream.write(data) 
     data = wf.readframes(CHUNK) 

    stream.stop_stream() 
    stream.close() 

    p.terminate() 


if __name__ == "__main__": 

    while True: 
     #If the 'a' key is pressed: start a new process that calls playNote 
     #and pass in the file name for a note. 
     if ord(getch()) == 97: #a 

      mp.Process(target=playNote, args=("F:\Project Harpsichord\The wavs\A1.wav",)).start() 

     #If the 's' key is pressed: start a new process that calls playNote 
     #and pass in the file name for another note. 
     if ord(getch()) == 115: #s 

      mp.Process(target=playNote, args=("F:\Project Harpsichord\The wavs\A0.wav",)).start() 

मूल रूप से जब भी मैं एक नई wav खेलना चाहते हैं, मैं एक नया प्रक्रिया है कि playNote समारोह में कोड चलाता है शुरू कर दिया है: एक ही रास्ता है कि मैं पूरा करने के लिए मैं चाहता था पाया इस था। जैसा कि मैंने पहले ही कहा है कि मैं संभावित रूप से इनमें से 100 में से एक बार खेल सकता हूं। यह कहना पर्याप्त है कि पाइथन दुभाषिया की एक सौ प्रतियां एक बार में चल रही हैं, जो लगभग मेरे कंप्यूटर को दुर्घटनाग्रस्त कर देती है। मैंने बहु-थ्रेडिंग के साथ एक समान दृष्टिकोण की भी कोशिश की, लेकिन एक ही समस्या थी।

This post एक साथ कई WAV फ़ाइलों को मिश्रित करने का एक तरीका दिखाता है ताकि उन्हें एक ही समय में खेला जा सके, लेकिन चूंकि मेरा प्रोग्राम जरूरी नहीं है कि यह एक ही समय में आवाज़ें शुरू हो जाए, तो यह सुनिश्चित नहीं होगा कि यह काम करेगा। मुझे एक ही समय में एकाधिक नोट्स खेलने के लिए एक प्रभावी तरीका चाहिए। चाहे यह किसी अन्य पुस्तकालय के रूप में आता है, या यहां तक ​​कि एक अलग भाषा है, मुझे वास्तव में परवाह नहीं है।

+1

क्या आपने मल्टीप्रोसेसिंग के बजाय थ्रेडिंग का उपयोग करने का प्रयास किया है? – disflux

+0

कई (8 तक) ध्वनियों को एक साथ खेलने के लिए, आप ['pygame.mixer.Sound()'] (http://stackoverflow.com/q/6004887/4279) का उपयोग कर सकते हैं। 'pygame' कुंजीपटल इनपुट प्राप्त करने के लिए एक पोर्टेबल तरीका भी प्रदान करता है। – jfs

+0

@disflux आपकी प्रतिक्रिया के लिए धन्यवाद। हां मैंने थ्रेडिंग मॉड्यूल के साथ एक समान दृष्टिकोण का प्रयास किया था, लेकिन इसी तरह की अंतराल की समस्याएं थीं। –

उत्तर

2

मैंने जेएफ सेबस्टियन जैसे पायगैम की जांच की। यह वही था जो मुझे चाहिए था। मैंने pygame.mixer.set_num_channels() के साथ pygame.mixer.Sound() का उपयोग किया। यहां मैं क्या आया था।

import pygame as pg 
import time 

pg.mixer.init() 
pg.init() 

a1Note = pg.mixer.Sound("F:\Project Harpsichord\The wavs\A1.wav") 
a2Note = pg.mixer.Sound("F:\Project Harpsichord\The wavs\A0.wav") 

pg.mixer.set_num_channels(50) 

for i in range(25): 
    a1Note.play() 
    time.sleep(0.3) 
    a2Note.play() 
    time.sleep(0.3) 
+0

अच्छा, यह आसान था v_v – Roman

2

यह वास्तव में आपकी समस्या का समाधान नहीं करता है, लेकिन यह टिप्पणियों के लिए बहुत लंबा है, और यह उपयोगी हो सकता है। मैंने इसे एक झटका दिया, कुछ मोर्चों पर पराजित हो गया - छोड़कर पिज्जा के लिए जा रहा था। ऑडियो वास्तव में मेरी बात नहीं है, लेकिन इसके साथ खेलना बहुत मजेदार था।

Pydub एक नज़र दें। मैंने कुछ तरीकों से खेला है, लेकिन कोई संतोषजनक सफलता नहीं मिली है। This answer यहां दो सिग्नल अच्छी तरह से जोड़ने के बारे में कुछ चीजें बताते हैं। मुझे लगता है कि क्लिपिंग के कारण आपके पास स्थिर है।

क्षमा करें कि मैं उद्धार नहीं था, लेकिन मैं भी सब बातों मैं मामले में बनाया है ताकि आप को या किसी और से कुछ हड़पने के लिए चाहता है पोस्ट कर सकते हैं:

#using python 2.7 
#example animal sounds from http://www.wavsource.com/animals/animals.htm 
    #note that those sounds have lots of different sampling rates and encoding types. Causes problems. 
#required installs: 
    #numpy 
    #scipy 
    #matplotlib 
    #pyaudio  -sudo apt-get install python-pyaudio 
    #pydub:   -pip install pydub 


def example(): 
    "example sounds and random inputs" 
    sExampleSoundsDir = "/home/roman/All/Code/sound_files" 
    sExampleFile1 = 'bird.wav' 
    sExampleFile2 = 'frog.wav' 
    oJ = Jurgenmeister(sExampleSoundsDir) 

    #load audio into numpy array 
    dSound1 = oJ.audio2array(sExampleFile1) 
    dSound2 = oJ.audio2array(sExampleFile2) 

    #Simply adding the arrays is noisy... 
    dResSound1 = oJ.resample(dSound1) 
    dResSound2 = oJ.resample(dSound2) 
    dJoined = oJ.add_sounds(dResSound1, dResSound2) 

    #pydub method 
    oJ.overlay_sounds(sExampleFile1, sExampleFile2) 

    #listen to the audio - mixed success with these sounds. 
    oJ.play_array(dSound1) 
    oJ.play_array(dSound2) 
    oJ.play_array(dResSound1) 
    oJ.play_array(dResSound2) 
    oJ.play_array(dJoined) 

    #see what the waveform looks like 
    oJ.plot_audio(dJoined) 




class Jurgenmeister: 
    """ 
    Methods to play as many sounds on command as necessary 
    Named in honour of op, and its as good a name as I can come up with myself. 
    """ 

    def __init__(self, sSoundsDir): 
     import os 
     import random 
     lAllSounds = os.listdir(sSoundsDir) 
     self.sSoundsDir = sSoundsDir 
     self.lAllSounds = lAllSounds 
     self.sRandSoundName = lAllSounds[random.randint(0, len(lAllSounds)-1)] 



    def play_wave(self, sFileName): 
     """PyAudio play a wave file.""" 

     import pyaudio 
     import wave 
     iChunk = 1024 
     sDir = "{}/{}".format(self.sSoundsDir, sFileName) 
     oWave = wave.open(sDir, 'rb') 
     oPyaudio = pyaudio.PyAudio() 

     oStream = oPyaudio.open(
      format = oPyaudio.get_format_from_width(oWave.getsampwidth()), 
      channels = oWave.getnchannels(), 
      rate = oWave.getframerate(), 
      output = True 
     ) 

     sData = oWave.readframes(iChunk) 
     while sData != '': 
      oStream.write(sData) 
      sData = oWave.readframes(iChunk) 

     oStream.stop_stream() 
     oStream.close() 
     oPyaudio.terminate() 



    def audio2array(self, sFileName): 
     """ 
     Returns monotone data for a wav audio file in form: 
      iSampleRate, aNumpySignalArray, aNumpyTimeArray 

      Should perhaps do this with scipy again, but I threw that code away because I wanted 
      to try the pyaudio package because of its streaming functions. They defeated me. 
     """ 
     import wave 
     import numpy as np 

     sDir = "{}/{}".format(self.sSoundsDir, sFileName) 
     oWave = wave.open(sDir,"rb") 
     tParams = oWave.getparams() 
     iSampleRate = tParams[2] #frames per second 
     iLen = tParams[3] # number of frames 

     #depending on the type of encoding of the file. Usually 16 
     try: 
      sSound = oWave.readframes(iLen) 
      oWave.close() 

      aSound = np.fromstring(sSound, np.int16) 
     except ValueError: 
      raise ValueError("""wave package seems to want all wav incodings to be in int16, else it throws a mysterious error. 
       Short way around it: find audio encoded in the right format. Or use scipy.io.wavfile. 
       """) 

     aTime = np.array([float(i)/iSampleRate for i in range(len(aSound))]) 

     dRet = { 
      'iSampleRate': iSampleRate, 
      'aTime': aTime, 
      'aSound': aSound, 
      'tParams': tParams 
     } 

     return dRet 



    def resample(self, dSound, iResampleRate=11025): 
      """resample audio arrays 
      common audio sample rates are 44100, 22050, 11025, 8000 

      #creates very noisy results sometimes. 
      """ 
      from scipy import interpolate 
      import numpy as np 
      aSound = np.array(dSound['aSound']) 

      iOldRate = dSound['iSampleRate'] 
      iOldLen = len(aSound) 
      rPeriod = float(iOldLen)/iOldRate 
      iNewLen = int(rPeriod*iResampleRate) 

      aTime = np.arange(0, rPeriod, 1.0/iOldRate) 
      aTime = aTime[0:iOldLen] 
      oInterp = interpolate.interp1d(aTime, aSound) 

      aResTime = np.arange(0, aTime[-1], 1.0/iResampleRate) 
      aTime = aTime[0:iNewLen] 

      aResSound = oInterp(aResTime) 
      aResSound = np.array(aResSound, np.int16) 

      tParams = list(x for x in dSound['tParams']) 
      tParams[2] = iResampleRate 
      tParams[3] = iNewLen 
      tParams = tuple(tParams) 

      dResSound = { 
       'iSampleRate': iResampleRate, 
       'aTime': aResTime, 
       'aSound': aResSound, 
       'tParams': tParams 
      } 

      return dResSound 



    def add_sounds(self, dSound1, dSound2): 
     """join two sounds together and return new array 
     This method creates a lot of clipping. Not sure how to get around that. 
     """ 
     if dSound1['iSampleRate'] != dSound2['iSampleRate']: 
      raise ValueError('sample rates must be the same. Please resample first.') 

     import numpy as np 

     aSound1 = dSound1['aSound'] 
     aSound2 = dSound2['aSound'] 

     if len(aSound1) < len(aSound2): 
      aRet = aSound2.copy() 
      aRet[:len(aSound1)] += aSound1 
      aTime = dSound2['aTime'] 
      tParams = dSound2['tParams'] 
     else: 
      aRet = aSound1.copy() 
      aRet[:len(aSound2)] += aSound2 
      aTime = dSound1['aTime'] 
      tParams = dSound1['tParams'] 


     aRet = np.array(aRet, np.int16) 

     dRet = { 
      'iSampleRate': dSound1['iSampleRate'], 
      'aTime': aTime, 
      'aSound': aRet, 
      'tParams': tParams 
     } 

     return dRet 



    def overlay_sounds(self, sFileName1, sFileName2): 
     "I think this method warrants a bit more exploration 
     Also very noisy." 
     from pydub import AudioSegment 

     sDir1 = "{}/{}".format(self.sSoundsDir, sFileName1) 
     sDir2 = "{}/{}".format(self.sSoundsDir, sFileName2) 

     sound1 = AudioSegment.from_wav(sDir1) 
     sound2 = AudioSegment.from_wav(sDir2) 

     # mix sound2 with sound1, starting at 0ms into sound1) 
     output = sound1.overlay(sound2, position=0) 

     # save the result 
     sDir = "{}/{}".format(self.sSoundsDir, 'OUTPUT.wav') 
     output.export(sDir, format="wav") 



    def array2audio(self, dSound, sDir=None): 
     """ 
     writes an .wav audio file to disk from an array 
     """ 
     import struct 
     import wave 
     if sDir == None: 
      sDir = "{}/{}".format(self.sSoundsDir, 'OUTPUT.wav') 

     aSound = dSound['aSound'] 
     tParams = dSound['tParams'] 
     sSound = struct.pack('h'*len(aSound), *aSound) 

     oWave = wave.open(sDir,"wb") 
     oWave.setparams(tParams) 
     oWave.writeframes(sSound) 
     oWave.close() 



    def play_array(self, dSound): 
     """Tried to use use pyaudio to play array by just streaming it. It didn't behave, and I moved on. 
     I'm just not getting the pyaudio stream to play without weird distortion 
     when not loading from file. Perhaps you have more luck. 
     """ 
     self.array2audio(dSound) 
     self.play_wave('OUTPUT.wav') 



    def plot_audio(self, dSound): 
     "just plots the audio array. Nice to see plots when things are going wrong." 
     import matplotlib.pyplot as plt 
     plt.plot(dSound['aTime'], dSound['aSound']) 
     plt.show() 




if __name__ == "__main__": 
    example() 

मैं भी इस त्रुटि मिलती है जब मैं लहर का उपयोग करता हूं। यह अभी भी काम करता है, इसलिए मैं इसे अनदेखा करता हूं। Problem seems to be widespread। त्रुटि रेखाएं:

ALSA lib pcm_dsnoop.c:618:(snd_pcm_dsnoop_open) unable to open slave 
ALSA lib pcm_dmix.c:1022:(snd_pcm_dmix_open) unable to open slave 
ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear 
ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe 
ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side 
bt_audio_service_open: connect() failed: Connection refused (111) 
bt_audio_service_open: connect() failed: Connection refused (111) 
bt_audio_service_open: connect() failed: Connection refused (111) 
bt_audio_service_open: connect() failed: Connection refused (111) 
ALSA lib pcm_dmix.c:1022:(snd_pcm_dmix_open) unable to open slave 
Cannot connect to server socket err = No such file or directory 
Cannot connect to server request channel 
jack server is not running or cannot be started 

शुभकामनाएँ!

+0

धन्यवाद वैसे भी (; –