似乎无法在原始Python中编写双通道波形文件(无波模块)

问题描述 投票:0回答:1

我正在尝试学习一些关于音频编程的知识,所以我决定看看我是否可以弄清楚如何生成正弦波并将其写入.wav文件。从参考here,我收集到每个通道只是在文件末尾的数据块中交错。但是,我生成的wav文件似乎只在左声道播放。我还将我的输出与真正的440hz A进行了比较,并注意到它比预期的低八度。

我想象的是,我用来收听文件的程序将数据解释为单个通道,并且由于每个样本都被复制一次,因此以预定频率的1/2播放波形。

我知道有一个Python模块可以帮助编写wav文件,但这是一个教育项目,我正在尝试学习编写二进制文件和wav文件格式。

为什么我似乎无法在两个频道中播放此文件?任何帮助将不胜感激。

我为这个凌乱的代码道歉,一旦我弄清楚这个最后一个bug,我打算稍微重构一下。

import struct
import math

# Frequency Table
A4 = 440.0



#Misc inputs
waveDuration = 3
amp_16 = 32760

# Wave Header

# Chunk Descriptor
chunkID = b'\x52\x49\x46\x46' #RIFF

hFormat = b'\x57\x41\x56\x45' #WAVE

# fmtSubChunk
fChunkID = b'\x66\x6d\x74\x20' #'fmt '
fChunkSize = 16 # 16 for PCM
audioFormat = 1 # 1 for PCM
numChannels = 2
sampleRate = 48000
bitsPerSample = 16
byteRate = int(sampleRate * numChannels * bitsPerSample / 8)

blockAlign = int(numChannels * bitsPerSample / 8)

# dataSubChunk
numSamples = waveDuration * sampleRate * numChannels
dChunkID = b'\x64\x61\x74\x61' #DATA
dChunkSize = int(numSamples * bitsPerSample / 8) 

chunkSize = dChunkSize + 36 + 8 

# Generate Sin Wave
def generateSin(sampleRate, bitDepth, frequency, amplitude, duration):
    data = [0] * sampleRate * duration

    angle = frequency * 2 * math.pi

    cur_sample = 0
    for sample in data:
        data[cur_sample] = amplitude * (math.sin(angle * cur_sample/ sampleRate))
        cur_sample += 1

    return data

# Write .wav file
waveFile = open('test.wav', 'wb')

# Header
waveFile.write(chunkID)
waveFile.write(struct.pack('<i', chunkSize))
waveFile.write(hFormat)

# Format Subchunk
waveFile.write(fChunkID)
waveFile.write(struct.pack('<i', fChunkSize))
waveFile.write(struct.pack('<h', audioFormat))
waveFile.write(struct.pack('<h', numChannels))
waveFile.write(struct.pack('<i', sampleRate))
waveFile.write(struct.pack('<i', byteRate))
waveFile.write(struct.pack('<h', blockAlign))
waveFile.write(struct.pack('<h', bitsPerSample))

# Data Subchunk
waveFile.write(dChunkID)
waveFile.write(struct.pack('<i', dChunkSize))



for samp in generateSin(sampleRate, bitsPerSample, A4, amp_16, 1):

    waveFile.write(struct.pack('<i', int(round(samp))))
    waveFile.write(struct.pack('<i', int(round(samp)))) 

waveFile.close()
python audio wav sin
1个回答
1
投票

学习wav文件的好方法。 16位的样本大小意味着每个通道是16位。你获取正弦波的样本值,将其打包成4个字节(32位),这样就可以得到像XX00这样的东西,其中XX是第一个通道的正确16位值,第二个通道是00,所以第二个通道只有零。之后 - 你再次写相同的值,所以你复制了上一个样本的数据,这就是你的频率错误的原因:enter image description here改变你的for循环

for samp in generateSin(sampleRate, bitsPerSample, A4, amp_16, 1):
    waveFile.write(struct.pack('<i', int(round(samp))))
    waveFile.write(struct.pack('<i', int(round(samp))))

至 -

for samp in generateSin(sampleRate, bitsPerSample, A4, amp_16, 1):
    waveFile.write(struct.pack('<h', int(round(samp))))
    waveFile.write(struct.pack('<h', int(round(samp))))

现在,您将一次只写2个字节,即一个通道,然后您将再次为第二个通道写入相同的值。频率不是440Hz而是500Hz - 我认为这是由于数字四舍五入。

© www.soinside.com 2019 - 2024. All rights reserved.