1. 程式人生 > >Python3+疊加兩個音訊檔案,實現混音

Python3+疊加兩個音訊檔案,實現混音

將兩個單聲道的音訊檔案疊加成一個新的音訊檔案。
實現:a + b = c(新)

同理,如果用 c - b 可以得到檔案a

同理,也可以將多個單聲道音訊檔案疊加到一起。

注意:

  • 兩個檔案要是相同聲道的檔案,這裡的程式碼只適用1聲道的。
  • 兩個音訊檔案的rate也要是相同的。
  • 當兩個音訊檔案的長度不同,需要將較短的音訊檔案補上靜音資料,這裡都是將靜音新增到了音訊檔案後。
import os
import wave
import numpy as np
import pyaudio

file1 = os.path.join(os.path.abspath(os.path.dirname(os.path.dirname(__file__))), '音訊檔案/demo1.wav')
file2 = os.path.join(os.path.abspath(os.path.dirname(os.path.dirname(__file__))), '音訊檔案/demo2.wav')

f1 = wave.open(file1, 'rb')
f2 = wave.open(file2, 'rb')

# 音訊1的資料
params1 = f1.getparams()
nchannels1, sampwidth1, framerate1, nframes1, comptype1, compname1 = params1[:6]
print(nchannels1, sampwidth1, framerate1, nframes1, comptype1, compname1)
f1_str_data = f1.readframes(nframes1)
f1.close()
f1_wave_data = np.fromstring(f1_str_data, dtype=np.int16)

# 音訊2的資料
params2 = f2.getparams()
nchannels2, sampwidth2, framerate2, nframes2, comptype2, compname2 = params2[:6]
print(nchannels2, sampwidth2, framerate2, nframes2, comptype2, compname2)
f2_str_data = f2.readframes(nframes2)
f2.close()
f2_wave_data = np.fromstring(f2_str_data, dtype=np.int16)

# 對不同長度的音訊用資料零對齊補位
if nframes1 < nframes2:
    length = abs(nframes2 - nframes1)
    temp_array = np.zeros(length, dtype=np.int16)
    rf1_wave_data = np.concatenate((f1_wave_data, temp_array))
    rf2_wave_data = f2_wave_data
elif nframes1 > nframes2:
    length = abs(nframes2 - nframes1)
    temp_array = np.zeros(length, dtype=np.int16)
    rf2_wave_data = np.concatenate((f2_wave_data, temp_array))
    rf1_wave_data = f1_wave_data
else:
    rf1_wave_data = f1_wave_data
    rf2_wave_data = f2_wave_data

# ================================
# 合併1和2的資料
new_wave_data = rf1_wave_data + rf2_wave_data
new_wave = new_wave_data.tostring()

p = pyaudio.PyAudio()
CHANNELS = 1
FORMAT = pyaudio.paInt16
RATE = 44100

# 實現錄音
def record(re_frames, WAVE_OUTPUT_FILENAME):
    print("開始錄音")
    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(re_frames)
    wf.close()
    print("關閉錄音")

record(new_wave, 'demo1+2.wav')