福岡の社会人データサイエンティストの部屋

データサイエンスを極めるため、日々の学習を綴っています。

E-X NSynthで新しい音を作ってみた!【図解速習DeepLearning】#019



こんにちは!こーたろーです。


昨日は、データサイエンスのオンラインイベントに参加してきました。


皆さん、いろいろな現場での悩みなどがあり、データサイエンスの位置づけとは!みたいなことで盛り上がっていました。


データサイエンスは現場あって初めて価値がでますし、データがないと何も始まらないということが言われています。


早く現場でやってみたいですね。勉強だけでは技術的に身につかない部分が多いです。特にコンサルの部分。




それでは今回も【図解速習DEEP LEARNING】やっていきます!


今日は、Googleの深層学習のアート適用プロジェクトMagenta(https://magenta.tensorflow.org/)を使って、音声を合成することで、新しい音を作ってみます。



今回は、さすがにMagentaというモジュールを使うのですが、Python3非対応だったため、修正に時間がかかりました。


時間がかかってかかって・・・・諦めました(笑


ということで、Python2.7でいきました。


現在、通常のファイル作成からいくと、Python3しか選択できないことから、下記のページからPython2系のファイルを作成します。


https://colab.research.google.com/notebook#create=true&language=python2


ではでは。。。


今回使用するのは、「WaveNet style Autoencoder」で、学習済みのモデルを活用していきます。


学習時の入力には、「The N-Synth Dataset」を使います。


出力としては、学期の合成から生まれた新たなサウンドが出力されます。

環境構築

事前学習済みのNSynthモデルをダウンロード・選択していきます。


Google ColaboratoryはGPUを選択して動かす方がいいでしょう。

%tensorflow_version 1.x

print('Installing Magenta...\n')
!pip install -q magenta
print('Installing ffmpeg...\n')
!echo "Yes" | apt-get install ffmpeg > /dev/null


print('Downloading Pretrained Models...\n')
print('Getting Instruments Model...\n')
!gsutil -q -m cp -R gs://download.magenta.tensorflow.org/models/nsynth/wavenet-ckpt.tar /content/
print('Getting Voices Model...\n')
!gsutil -q -m cp -R gs://download.magenta.tensorflow.org/models/nsynth/wavenet-voice-ckpt.tar.gz /content/
!cd /content/
!tar -xvf wavenet-ckpt.tar > /dev/null
!tar -xvf wavenet-voice-ckpt.tar.gz > /dev/null


print('Importing Modules...\n')
import os
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import Audio
%matplotlib inline

from google.colab import files
from magenta.models.nsynth import utils
from magenta.models.nsynth.wavenet import fastgen
from magenta.music.notebook_utils import colab_play as play

def upload(sample_length, sr):
  '''Upload a .wav file.'''
  filemap = files.upload()
  file_list, audio_list = [], []
  for key, value in filemap.iteritems():
    fname = os.path.join('/content/', key)
    with open(fname, 'w') as f:
      f.write(value)
    audio = utils.load_audio(fname, sample_length=sample_length, sr=sr)
    file_list.append(fname)
    audio_list.append(audio)
  return file_list, audio_list

download = files.download

get_name = lambda f: os.path.splitext(os.path.basename(f))[0]

print('Sucess!! Environment is now setup.')



f:id:dsf-kotaro:20210224210248p:plain


モデルの選択

モデルは、以下の2通りから選ぶことができます。

  • NSynth Datasetの個々の楽器で学習したもの
  • アートプロジェクトのために野生の様々な声で学習したもの


#@title Choose a Model { vertical-output: true, run: "auto" }
Model = "Voices" #@param ["Instruments", "Voices"] {type:"string"}
ckpts = {'Instruments': '/content/wavenet-ckpt/model.ckpt-200000',
         'Voices': '/content/wavenet-voice-ckpt/model.ckpt-200000'}

ckpt_path = ckpts[Model]
print('Using model pretrained on %s.' % Model)



f:id:dsf-kotaro:20210224210336p:plain

合成する音の時間[秒]を設定する。

全てのファイルは、モデルへの入出力用に16kHzへダウンサンプリングされます。


そのため、16kHz×秒数になるようにトリミングまたは無音で埋められます。

#@title Set Sound Length (in Seconds) { vertical-output: true, run: "auto" }
Length = 4.0 #@param {type:"number"}
SR = 16000
SAMPLE_LENGTH = int(SR * Length)



f:id:dsf-kotaro:20210224210411p:plain

サウンドファイルの準備

サウンドファイルは、手元にある場合はそちらを使ってみてください。


今回は、「Freesound - Freesound」というサイトから、以下の4つの音源を入手しています。


リンクを貼っておくので、聴いてみてください。






try:
  file_list, audio_list = upload(sample_length=SAMPLE_LENGTH, sr=SR)
  names = [get_name(f) for f in file_list]

  for i in range(len(audio_list)):
    audio_list[i] = audio_list[i] / np.abs(audio_list[i]).max()

    if len(audio_list[i]) < SAMPLE_LENGTH:
      padding = SAMPLE_LENGTH - len(audio_list[i])
      audio_list[i] = np.pad(audio_list[i], (0, padding), 'constant')

  audio_list = np.array(audio_list)
except Exception as e:
  print('Upload Cancelled')
  print(e)



ウィッジでファイルを選択できるようになりますので、1回で利用するファイルの全てを選択し、アップロードしてください。


ファイルのアップロードは数分かかります。


f:id:dsf-kotaro:20210224210510p:plain



データセットを前処理(オーディオのエンコード



WaveNetのfastgenを用いて、オーディオのエンコーディングを行っていきます。

audio = np.array(audio_list)
z = fastgen.encode(audio, ckpt_path, SAMPLE_LENGTH)
print('Encoded %d files' % z.shape[0])

z_list = [z_ for z_ in z]
name_list = ['recon_' + name_ for name_ in names]

n = len(names)
for i in range(n - 1):
  for j in range(i + 1, n):
    new_z = (z[i] + z[j]) / 2.0
    new_name = 'interp_' + names[i] + '_X_'+ names[j]
    z_list.append(new_z)
    name_list.append(new_name)

print("%d total: %d reconstructions and %d interpolations" % (len(name_list), n, len(name_list) - n))





エンコーディング結果の可視化



オーディオの圧縮表現ではありますが、構造を可視化してみます。

#@title Visualize Audio and Encoding { vertical-output: true, run: "auto" }
SoundFile = 3 #@param {type:"slider", min:0, max:10, step:1}
file_number = SoundFile

try:
  print(names[file_number])
  play(audio_list[file_number], sample_rate=SR)
  plt.figure()
  plt.plot(audio_list[file_number])
  plt.title('Audio Signal')

  plt.figure()
  plt.plot(z_list[file_number])
  plt.title('NSynth Encoding')
except Exception as e:
  print e



f:id:dsf-kotaro:20210224205034p:plain


f:id:dsf-kotaro:20210224205101p:plain


f:id:dsf-kotaro:20210224205130p:plain


f:id:dsf-kotaro:20210224205149p:plain



音の合成

print('Total Iterations to Complete: %d\n' % SAMPLE_LENGTH)

encodings = np.array(z_list)
save_paths = ['/content/' + name + '.wav' for name in name_list]
fastgen.synthesize(encodings,
                   save_paths=save_paths,
                   checkpoint_path=ckpt_path,
                   samples_per_save=int(SAMPLE_LENGTH / 10))




合成した音を視聴してみる



合成した音声を聴いてみます。

print("Originals:\n")
for fname in file_list:
  synth_audio = utils.load_audio(fname,
                                 sample_length=SAMPLE_LENGTH,
                                 sr=SR)
  print(get_name(fname))
  play(synth_audio, sample_rate=SR)

for i, fname in enumerate(save_paths):
  if i == 0:
    print("Reconstructions:\n")
  if i == len(file_list):
    print("Interpolations:\n")
  synth_audio = utils.load_audio(fname,
                                 sample_length=SAMPLE_LENGTH,
                                 sr=SR)
  print(get_name(fname))
  play(synth_audio, sample_rate=SR)



3通りの音声を表示しています。

  • 生音(4通り)



f:id:dsf-kotaro:20210224225453p:plain



f:id:dsf-kotaro:20210224225645p:plain

  • 合成後の音(6通り)



f:id:dsf-kotaro:20210224225710p:plain

まとめ



今回は音声の合成を試してみました。


新たなシンセサイザーとして使えそうですね。


引き続き、音声認識やっていきます!


ではでは。