TransWikia.com

Numpyでの音データ同士の重ね合わせ

スタック・オーバーフロー Asked by user41237 on December 30, 2021

Pythonでnumpy配列同士を和の演算すると各要素の和になるということらしく表示されるグラフに影響が出てしまいました。

それを回避するためにnumpyの何かしらを用いて音データの重ね合わせをしたいです。
song1に10秒の曲データ、song2に1秒のノイズデータがあるとして
song1の5-6秒の1秒間にノイズを重ね合わせて、それを反映させた音を聴けるようにするにはどうすればよいのでしょうか?

mixmusic=np.insert(song1,song1[5*sr:6*sr],song2)
IPython.display.Audio(mixmusic, rate=sr) #完成音データを聞ける様に

など、様々試してみましたが、どうやってもノイズが10秒の曲の冒頭や最後に挿入されてしまいます。

以下のノイズ波形とsong1の波形を互いに影響が及ばないように重ね合わせたいです。
ノイズの最大値はsong1の最大値と一致させるという処理をしています。
単純にsong1[5sr:6sr]+=song2のようにすると振幅値がsong1とsong2の最大値を超えてしまうのでそうならないようにしたいです。

song2(ノイズの波形)

song1の波形

単純な和で実現させた結果

2 Answers

挿入するwavファイルの先頭と末尾に無音区間を入れて、行列の要素数を揃えた上で合成すること自体は可能です。

import numpy as np
from scipy.io import wavfile

rate = 44100
pad_start_sec = 5 # データ挿入位置

# サンプルデータ(sin.wav, noise.wav)作成
def create_samplings():
    seconds = 10 # 正弦波データ10秒
    sin_wave = [i / 20 for i in range(0, rate * seconds)] # i/20は低音に抑えるため
    sin = np.int16(np.sin(sin_wave) * 32767)
    wavfile.write('sin.wav', rate, sin)
    noise = np.int16(np.random.uniform(-0.1, 0.1, rate) * 32767) # ノイズデータ 1秒
    wavfile.write('noise.wav', rate, noise)

create_samplings()
fs, sin = wavfile.read('sin.wav')
_, noise = wavfile.read('noise.wav')

# ノイズの前後に無音区間を追加
pad = np.int16(np.zeros(sin.size) * 32767)
pad_start = rate * 5
pad[pad_start: pad_start + noise.size] = noise
# 合成して書き出し
z = sin + pad
wavfile.write('out.wav', fs, z)

しかしライブラリを使える環境ならば、pydubなどのライブラリ利用をお勧めします。

pydub.AudioSegment.overlayを使うサンプルコード

from pydub import AudioSegment

sin = AudioSegment.from_file("sin.wav")
noise = AudioSegment.from_file("noise.wav")
output = sin.overlay(noise, position=5000)
output.export("out.wav", format='wav')

Answered by payaneco on December 30, 2021

10秒の曲データsong1と、1秒のノイズデータsong2がある。
song1の5-6秒の1秒間にノイズ(song2)を重ね合わせたい。
という事ですから、

出来上がった曲は
0-5秒 song1の0-5秒と同じ (なにも変化させていない)
5-6秒 song1の5-6秒とsong2とを重ね合わせたもの
6-10秒 song1の6-10秒と同じ (なにも変化させていない)
になるはずです。

song1の0-5秒と、song1の5-6秒、song1の6-10秒は、
song1[0:5 * sr]、song1[5 * sr : 6 * sr]、song1[6 * sr : 10 * sr]のように、song1のスライスで得られます。

song1[0 : 5 * sr]と、song1[5 * sr : 6 * sr]とsong2とを重ね合わせたものと、song1[6 * sr : 10 * sr]の3つを連結すれば、質問者が望んでいる曲データになるのではないでしょうか?

Answered by Fumu 7 on December 30, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP