使用PyAudio生成波形音频时程序启停/静音阶段爆音问题排查求助
使用PyAudio生成波形音频时程序启停/静音阶段爆音问题排查求助
我正在写一个Python脚本,用来生成指定频率的各种波形音频。我用了PyAudio库(C语言PortAudio的Python封装)来输出基于8位整数的音频,目前音频播放本身效果还不错,只有几个小问题不是我现在关注的重点。
但程序启动或者结束的时候会出现很刺耳的爆音/噼啪声。我知道这种问题可能是音量突变导致的,但我尝试在程序终止前逐步降低音量的操作要么完全没用,甚至还让问题变得更严重了。
我把源代码贴在下面,想请教各位:这个爆音到底是什么原因导致的?是PyAudio本身存在未修复的深层问题?还是我存储音频强度值的方式有问题?会不会是库冲突?或者我是不是漏掉了某个关键步骤?
import pyaudio import random import pygame import copy pygame.init() framerate = 60 frequency = 440 #Hertz (Oscillations per Second) samplerate = 16000 #Samples Per Second volume = 4 #out of 256 SPU = samplerate//framerate #Samples Per Update SPO = samplerate//frequency #Samples Per Oscillation #0: Pulse Wave #1: Triangle Wave #2: Sawtooth Wave #3: Noise mode = 0 lastvalue = 0 gentimer = 0 pulseswitch = 1 tritone = 0 noisemode = False noisetimer = 0 timer = pygame.time.Clock() window = pygame.display.set_mode((100,200)) speaker = pyaudio.PyAudio() channel = speaker.open(format=pyaudio.paUInt8,frames_per_buffer=SPU,channels=1,rate=samplerate,output=True) data = bytearray() lastdata = bytearray() killtimer = -1 while True: events = pygame.event.get() for event in events: if event.type == pygame.KEYDOWN: if event.key == pygame.K_1: mode = 1 elif event.key == pygame.K_2: mode = 2 elif event.key == pygame.K_3: mode = 3 elif event.key == pygame.K_0: mode = 0 elif event.key == pygame.K_m: if noisemode: noisemode = False else: noisemode = True elif event.key == pygame.K_SPACE: frequency = 261.6256 SPO = samplerate//frequency gentimer = 0 elif event.type == pygame.KEYUP: if event.key == pygame.K_SPACE: frequency = 440 SPO = samplerate//frequency gentimer = 0 elif event.type == pygame.QUIT: killtimer = 20 if mode == 0: for frame in range(SPU): gentimer += 1 if gentimer >= (samplerate/frequency)/2: gentimer = gentimer - ((samplerate/frequency)/2) if pulseswitch == 1: pulseswitch = 0 else: pulseswitch = 1 data.append(int(volume*pulseswitch/2)) elif mode == 1: for frame in range(SPU): gentimer += (1-2*pulseswitch) if gentimer >= (samplerate/frequency)/2: gentimer = ((samplerate/frequency))-gentimer pulseswitch = 1 elif gentimer < 0: gentimer = -gentimer pulseswitch = 0 tritone = gentimer/((samplerate/frequency)/2) data.append(int(volume*tritone)) elif mode == 2: for frame in range(SPU): gentimer += 1 if gentimer >= (samplerate/frequency): gentimer = gentimer-(samplerate/frequency) #print(gentimer) tritone = gentimer/(samplerate/frequency) data.append(int(volume*tritone)) elif mode == 3: for frame in range(SPU): gentimer += 1 if gentimer >= (samplerate/frequency): gentimer = 0 if noisemode: noisetimer += 1 if noisetimer >= 31: noisetimer = 0 random.seed(0) tritone = random.randint(0,255)/255 data.append(int(volume*tritone)) channel.write(bytes(data)) data = bytearray() timer.tick(framerate) if killtimer != -1: volume = volume*0.9 if volume < 0.1: break channel.stop_stream() channel.close() speaker.terminate()
备注:内容来源于stack exchange,提问作者Sad Robot
相关产品推荐
相关产品推荐

