在Python中创建一个无限长的正弦音

时间:2013-11-18 20:34:02

标签: python audio numpy sine pyaudio

我正在尝试用Python创建一个无限长的纯正弦音(所以我以后可以添加实时的开/关事件),虽然我可以播放音调,但它是不稳定和剪辑的。我的假设是,它要么是从下一个块开始,而不是在波形周期中与最后一个块结束时相同的位置,要么是计算下一个块的延迟,我不知道它是什么。

是否发生了这些事情,或者我是否犯了其他错误?此外,在不牺牲实时更改传入数据的能力的情况下,是否有更好的方法?

import time
import numpy
import pyaudio
import math

CHUNK = 4096
RATE = 44100

def sine(current_time, frequency=440):
    length = CHUNK
    factor = float(frequency) * (math.pi * 2) / RATE
    this_chunk = numpy.arange(length) + current_time
    return numpy.sin(this_chunk * factor)

def get_chunk():
    data = sine(time.time())
    return data * 0.1

def callback(in_data, frame_count, time_info, status):
    chunk = get_chunk() * 0.25
    data = chunk.astype(numpy.float32).tostring()
    return (data, pyaudio.paContinue)

p = pyaudio.PyAudio()
stream = p.open(format = pyaudio.paFloat32,
                channels = 2,
                rate = RATE,
                output = True,
                stream_callback = callback)

stream.start_stream()

while stream.is_active():
    time.sleep(0.1)

stream.stop_stream()
stream.close()

1 个答案:

答案 0 :(得分:-2)

看起来您需要进行一些优化,请参阅

https://wiki.python.org/moin/PythonSpeed/PerformanceTips

尝试:

import time
import numpy
import pyaudio
import math

CHUNK = 4096
RATE = 44100

MP = math.pi
NA = numpy.arange
NS = numpy.sin
TT = time.time
NF32 = numpy.float32
p = pyaudio.PyAudio()
PO = p.open
PC = pyaudio.paContinue
PF = pyaudio.paFloat32
TS = time.sleep

def sine(current_time, frequency=440):
    length = CHUNK
    factor = float(frequency) * (MP * 2) / RATE
    this_chunk = NA(length) + current_time
    return NS(this_chunk * factor)*  0.025



def callback(in_data, frame_count, time_info, status):
    chunk = sine(TT())
    data = chunk.astype(NF32).tostring()
    return (data, PC)


stream = PO(format = PF,
                channels = 2,
                rate = RATE,
                output = True,
                stream_callback = callback)

stream.start_stream()

while stream.is_active():
    TS(0.1)

stream.stop_stream()
stream.close()