😽
pythonで愛猫達に歌ってもらった
はじめに
私は2匹の愛猫達と暮らしています。
2匹の声で何か歌ってもらえたら面白いなと思い、今回作ってみました。
実行したコード
それぞれの猫の声を使って、
cat1には第九、cat2には主よ、人の望みの喜びよを歌ってもらいました。
1.cat1 (第九)
import librosa
import numpy as np
import sounddevice as sd
import soundfile as sf # ファイル保存用
# 1. 猫の声のピッチを変更する関数
def pitch_shift_cat_sound(cat_audio, sr, target_pitch):
pitches, magnitudes = librosa.piptrack(y=cat_audio, sr=sr)
avg_pitch = np.mean(pitches[pitches > 0]) # 平均ピッチを計算
semitones = 12 * np.log2(target_pitch / avg_pitch) # ピッチシフト量(セミトーン)
shifted_audio = librosa.effects.pitch_shift(cat_audio, sr=sr, n_steps=semitones)
return shifted_audio
# 2. 指定された音階に基づいて猫の声を生成
def generate_cat_music(cat_audio, sr, melodies, durations):
music = []
for melody, duration_per_note in zip(melodies, durations):
for note_pitch in melody:
if note_pitch is not None:
shifted_audio = pitch_shift_cat_sound(cat_audio, sr, note_pitch)
num_samples = int(sr * duration_per_note)
shifted_audio = shifted_audio[:num_samples]
music.append(shifted_audio)
else:
music.append(np.zeros(int(sr * duration_per_note))) # 無音(休符)
return np.concatenate(music)
# 3. WAVデータを再生
def play_audio(audio, sr):
sd.play(audio, sr)
sd.wait()
# メイン処理
if __name__ == "__main__":
# 録音した猫の声のファイル
cat_audio_path = "cat1_sound.wav"
cat_audio, sr = librosa.load(cat_audio_path, sr=None)
# 複数のメロディを定義
melody0 = [1318.51, 1318.51, 1396.913, 1567.982, 1567.982, 1396.913, 1318.51, 1174.659, 1046.502, 1046.502, 1174.659, 1318.51]
melody1 = [1318.51]
melody2 = [1174.659]
melody3 = [1174.659]
melody4 = [1318.51, 1318.51, 1396.913, 1567.982, 1567.982, 1396.913, 1318.51, 1174.659, 1046.502, 1046.502, 1174.659, 1318.51]
melody5 = [1174.659]
melody6 = [1046.502]
melody7 = [1046.502]
melody8 = [1174.659, 1174.659, 1318.51, 1046.502, 1174.659]
melody9 = [1318.51, 1396.913]
melody10 = [1318.51, 1046.502, 1174.659]
melody11 = [1318.51, 1396.913]
melody12 = [1318.51, 1174.659, 1046.502, 1174.659]
melody13 = [783.991]
melody14 = [1318.51, 1318.51, 1396.913, 1567.982, 1567.982, 1396.913, 1318.51, 1174.659, 1046.502, 1046.502, 1174.659, 1318.51]
melody15 = [1174.659]
melody16 = [1046.502]
melody17 = [1046.502]
# メロディリスト
melodies = [melody0, melody1, melody2, melody3,melody4, melody5, melody6, melody7, melody8,
melody9, melody10,melody11, melody12, melody13, melody14, melody15, melody16, melody17]
# 各メロディのノートの長さ(秒)
durations = [0.5, 0.8, 0.4,1.0, 0.5, 0.8, 0.4,1.0, 0.5, 0.4,0.5, 0.4, 0.5, 1.0, 0.5, 0.8, 0.4,1.2] # melody0: 0.5秒, melody1: 1秒, melody2: 0.5秒, melody3: 1秒
# 猫の声を音階に基づいて再構成
cat_music = generate_cat_music(cat_audio, sr, melodies, durations)
# 再生
play_audio(cat_music, sr)
# 保存
output_path = "cat_music_Btv_S_No9.wav"
sf.write(output_path, cat_music, sr)
print(f"音楽データを {output_path} に保存しました。")
2.cat2(主よ、人の望みの喜びよ)
import librosa
import numpy as np
import sounddevice as sd
import soundfile as sf # ファイル保存用
# 1. 猫の声のピッチを変更する関数
def pitch_shift_cat_sound(cat_audio, sr, target_pitch):
pitches, magnitudes = librosa.piptrack(y=cat_audio, sr=sr)
avg_pitch = np.mean(pitches[pitches > 0]) # 平均ピッチを計算
semitones = 12 * np.log2(target_pitch / avg_pitch) # ピッチシフト量(セミトーン)
shifted_audio = librosa.effects.pitch_shift(cat_audio, sr=sr, n_steps=semitones)
return shifted_audio
# 2. 指定された音階に基づいて猫の声を生成
def generate_cat_music(cat_audio, sr, melodies, durations):
music = []
for melody, duration_per_note in zip(melodies, durations):
for note_pitch in melody:
if note_pitch is not None:
shifted_audio = pitch_shift_cat_sound(cat_audio, sr, note_pitch)
num_samples = int(sr * duration_per_note)
shifted_audio = shifted_audio[:num_samples]
music.append(shifted_audio)
else:
music.append(np.zeros(int(sr * duration_per_note))) # 無音(休符)
return np.concatenate(music)
# 3. WAVデータを再生
def play_audio(audio, sr):
sd.play(audio, sr)
sd.wait()
# メイン処理
if __name__ == "__main__":
# 録音した猫の声のファイル
cat_audio_path = "cat2_sound.wav"
cat_audio, sr = librosa.load(cat_audio_path, sr=None)
# 複数のメロディを定義
melody0 = [1567.982, 1760, 1975.533, 2349.318, 2093.005, 2093.005, 2637.02, 2349.318, 2349.318, 3135.963, 2959.955, 3135.963, 2349.318, 1975.533, 1567.982, 1760, 1975.533, 2093.005 ]
melody1 = [2349.318, 2637.02, 2349.318, 2093.005, 1975.533, 1760, 1975.533, 1567.982, 1479.978, 1567.982, 1760, 1174.659, 1479.978, 1760, 2093.005, 1975.533, 1760, 1975.533 ]
melody2 = [1567.982, 1760, 1975.533, 2349.318, 2093.005, 2093.005, 2637.02, 2349.318, 2349.318, 3135.963, 2959.955, 3135.963, 2349.318, 1975.533, 1567.982, 1760, 1975.533, 1318.51 ]
melody3 = [2349.318, 2093.005, 1975.533, 1760, 1567.982, 1174.659, 1567.982, 1479.978, 1567.982, 1975.533, 2349.318, 3135.963, 2349.318, 1975.533, 1567.982, 1975.533, 2349.318 ]
melody4 = [3135.963]
# メロディリスト
melodies = [melody0, melody1, melody2, melody3, melody4]
# 各メロディのノートの長さ(秒)
durations = [0.7, 0.7, 0.7,0.7, 1.2] # melody0: 0.5秒, melody1: 1秒, melody2: 0.5秒, melody3: 1秒
# 猫の声を音階に基づいて再構成
cat_music = generate_cat_music(cat_audio, sr, melodies, durations)
# 再生
play_audio(cat_music, sr)
# 保存
output_path = "cat_music_Bach_JJoMD.wav"
sf.write(output_path, cat_music, sr)
print(f"音楽データを {output_path} に保存しました。")
まとめ
ちょっとした息抜きに猫に歌ってもらいました。
Discussion