Spaces:
Runtime error
Runtime error
add streamlit app and tidy
Browse files- .gitignore +2 -0
- README.md +5 -5
- app.py +4 -17
- src/audio_to_images.py → audio_to_images.py +22 -32
- audiodiffusion/__init__.py +40 -0
- {src → audiodiffusion}/mel.py +48 -8
- notebooks/test-mel.ipynb +3 -3
- notebooks/test-model.ipynb +0 -0
- requirements-lock.txt +51 -0
- requirements.txt +2 -2
- setup.cfg +19 -0
- setup.py +6 -0
- streamlit_app.py +22 -0
- src/train_unconditional.py → train_unconditional.py +34 -37
.gitignore
CHANGED
@@ -4,3 +4,5 @@ __pycache__
|
|
4 |
data*
|
5 |
ddpm-ema-audio-*
|
6 |
flagged
|
|
|
|
|
|
4 |
data*
|
5 |
ddpm-ema-audio-*
|
6 |
flagged
|
7 |
+
build
|
8 |
+
audiodiffusion.egg-info
|
README.md
CHANGED
@@ -28,7 +28,7 @@ You can play around with the model I trained on about 500 songs from my Spotify
|
|
28 |
#### Training can be run with Mel spectrograms of resolution 64x64 on a single commercial grade GPU (e.g. RTX 2080 Ti). The `hop_length` should be set to 1024 for better results.
|
29 |
|
30 |
```bash
|
31 |
-
python
|
32 |
--resolution 64 \
|
33 |
--hop_length 1024\
|
34 |
--input_dir path-to-audio-files \
|
@@ -38,7 +38,7 @@ python src/audio_to_images.py \
|
|
38 |
#### Generate dataset of 256x256 Mel spectrograms and push to hub (you will need to be authenticated with `huggingface-cli login`).
|
39 |
|
40 |
```bash
|
41 |
-
python
|
42 |
--resolution 256 \
|
43 |
--input_dir path-to-audio-files \
|
44 |
--output_dir data-256 \
|
@@ -49,7 +49,7 @@ python src/audio_to_images.py \
|
|
49 |
|
50 |
```bash
|
51 |
accelerate launch --config_file accelerate_local.yaml \
|
52 |
-
|
53 |
--dataset_name data-64 \
|
54 |
--resolution 64 \
|
55 |
--hop_length 1024 \
|
@@ -66,7 +66,7 @@ accelerate launch --config_file accelerate_local.yaml \
|
|
66 |
|
67 |
```bash
|
68 |
accelerate launch --config_file accelerate_local.yaml \
|
69 |
-
|
70 |
--dataset_name teticio/audio-diffusion-256 \
|
71 |
--resolution 256 \
|
72 |
--output_dir ddpm-ema-audio-256 \
|
@@ -86,7 +86,7 @@ accelerate launch --config_file accelerate_local.yaml \
|
|
86 |
|
87 |
```bash
|
88 |
accelerate launch --config_file accelerate_sagemaker.yaml \
|
89 |
-
|
90 |
--dataset_name teticio/audio-diffusion-256 \
|
91 |
--resolution 256 \
|
92 |
--output_dir ddpm-ema-audio-256 \
|
|
|
28 |
#### Training can be run with Mel spectrograms of resolution 64x64 on a single commercial grade GPU (e.g. RTX 2080 Ti). The `hop_length` should be set to 1024 for better results.
|
29 |
|
30 |
```bash
|
31 |
+
python audiodiffusion/audio_to_images.py \
|
32 |
--resolution 64 \
|
33 |
--hop_length 1024\
|
34 |
--input_dir path-to-audio-files \
|
|
|
38 |
#### Generate dataset of 256x256 Mel spectrograms and push to hub (you will need to be authenticated with `huggingface-cli login`).
|
39 |
|
40 |
```bash
|
41 |
+
python audiodiffusion/audio_to_images.py \
|
42 |
--resolution 256 \
|
43 |
--input_dir path-to-audio-files \
|
44 |
--output_dir data-256 \
|
|
|
49 |
|
50 |
```bash
|
51 |
accelerate launch --config_file accelerate_local.yaml \
|
52 |
+
audiodiffusion/train_unconditional.py \
|
53 |
--dataset_name data-64 \
|
54 |
--resolution 64 \
|
55 |
--hop_length 1024 \
|
|
|
66 |
|
67 |
```bash
|
68 |
accelerate launch --config_file accelerate_local.yaml \
|
69 |
+
audiodiffusion/train_unconditional.py \
|
70 |
--dataset_name teticio/audio-diffusion-256 \
|
71 |
--resolution 256 \
|
72 |
--output_dir ddpm-ema-audio-256 \
|
|
|
86 |
|
87 |
```bash
|
88 |
accelerate launch --config_file accelerate_sagemaker.yaml \
|
89 |
+
audiodiffusion/train_unconditional.py \
|
90 |
--dataset_name teticio/audio-diffusion-256 \
|
91 |
--resolution 256 \
|
92 |
--output_dir ddpm-ema-audio-256 \
|
app.py
CHANGED
@@ -1,23 +1,10 @@
|
|
1 |
import argparse
|
2 |
|
3 |
import gradio as gr
|
4 |
-
from PIL import Image
|
5 |
-
from diffusers import DDPMPipeline
|
6 |
|
7 |
-
from
|
8 |
-
|
9 |
-
mel = Mel(x_res=256, y_res=256)
|
10 |
-
model_id = "teticio/audio-diffusion-256"
|
11 |
-
ddpm = DDPMPipeline.from_pretrained(model_id)
|
12 |
-
|
13 |
-
|
14 |
-
def generate_spectrogram_and_audio():
|
15 |
-
images = ddpm(output_type="numpy")["sample"]
|
16 |
-
images = (images * 255).round().astype("uint8").transpose(0, 3, 1, 2)
|
17 |
-
image = Image.fromarray(images[0][0])
|
18 |
-
audio = mel.image_to_audio(image)
|
19 |
-
return image, (mel.get_sample_rate(), audio)
|
20 |
|
|
|
21 |
|
22 |
if __name__ == "__main__":
|
23 |
parser = argparse.ArgumentParser()
|
@@ -26,9 +13,9 @@ if __name__ == "__main__":
|
|
26 |
args = parser.parse_args()
|
27 |
|
28 |
demo = gr.Interface(
|
29 |
-
fn=generate_spectrogram_and_audio,
|
30 |
title="Audio Diffusion",
|
31 |
-
description=
|
32 |
This takes about 20 minutes without a GPU, so why not make yourself a cup of tea in the meantime?",
|
33 |
inputs=[],
|
34 |
outputs=[
|
|
|
1 |
import argparse
|
2 |
|
3 |
import gradio as gr
|
|
|
|
|
4 |
|
5 |
+
from audiodiffusion import AudioDiffusion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
+
audio_diffusion = AudioDiffusion()
|
8 |
|
9 |
if __name__ == "__main__":
|
10 |
parser = argparse.ArgumentParser()
|
|
|
13 |
args = parser.parse_args()
|
14 |
|
15 |
demo = gr.Interface(
|
16 |
+
fn=audio_diffusion.generate_spectrogram_and_audio,
|
17 |
title="Audio Diffusion",
|
18 |
+
description="Generate audio using Huggingface diffusers.\
|
19 |
This takes about 20 minutes without a GPU, so why not make yourself a cup of tea in the meantime?",
|
20 |
inputs=[],
|
21 |
outputs=[
|
src/audio_to_images.py → audio_to_images.py
RENAMED
@@ -1,8 +1,3 @@
|
|
1 |
-
# TODO
|
2 |
-
# run on sagemaker
|
3 |
-
# run with deepspeed
|
4 |
-
|
5 |
-
|
6 |
import os
|
7 |
import re
|
8 |
import io
|
@@ -12,17 +7,17 @@ import pandas as pd
|
|
12 |
from tqdm.auto import tqdm
|
13 |
from datasets import Dataset, DatasetDict, Features, Image, Value
|
14 |
|
15 |
-
from mel import Mel
|
16 |
|
17 |
|
18 |
def main(args):
|
19 |
-
mel = Mel(x_res=args.resolution,
|
|
|
|
|
20 |
os.makedirs(args.output_dir, exist_ok=True)
|
21 |
audio_files = [
|
22 |
-
os.path.join(root, file)
|
23 |
-
for
|
24 |
-
for file in files
|
25 |
-
if re.search("\.(mp3|wav|m4a)$", file, re.IGNORECASE)
|
26 |
]
|
27 |
examples = []
|
28 |
try:
|
@@ -35,31 +30,26 @@ def main(args):
|
|
35 |
continue
|
36 |
for slice in range(mel.get_number_of_slices()):
|
37 |
image = mel.audio_slice_to_image(slice)
|
38 |
-
assert (
|
39 |
-
|
40 |
-
)
|
41 |
with io.BytesIO() as output:
|
42 |
image.save(output, format="PNG")
|
43 |
bytes = output.getvalue()
|
44 |
-
examples.extend(
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
]
|
52 |
-
)
|
53 |
finally:
|
54 |
ds = Dataset.from_pandas(
|
55 |
pd.DataFrame(examples),
|
56 |
-
features=Features(
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
}
|
62 |
-
),
|
63 |
)
|
64 |
dsd = DatasetDict({"train": ds})
|
65 |
dsd.save_to_disk(os.path.join(args.output_dir))
|
@@ -69,8 +59,8 @@ def main(args):
|
|
69 |
|
70 |
if __name__ == "__main__":
|
71 |
parser = argparse.ArgumentParser(
|
72 |
-
description=
|
73 |
-
|
74 |
parser.add_argument("--input_dir", type=str)
|
75 |
parser.add_argument("--output_dir", type=str, default="data")
|
76 |
parser.add_argument("--resolution", type=int, default=256)
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import os
|
2 |
import re
|
3 |
import io
|
|
|
7 |
from tqdm.auto import tqdm
|
8 |
from datasets import Dataset, DatasetDict, Features, Image, Value
|
9 |
|
10 |
+
from audiodiffusion.mel import Mel
|
11 |
|
12 |
|
13 |
def main(args):
|
14 |
+
mel = Mel(x_res=args.resolution,
|
15 |
+
y_res=args.resolution,
|
16 |
+
hop_length=args.hop_length)
|
17 |
os.makedirs(args.output_dir, exist_ok=True)
|
18 |
audio_files = [
|
19 |
+
os.path.join(root, file) for root, _, files in os.walk(args.input_dir)
|
20 |
+
for file in files if re.search("\.(mp3|wav|m4a)$", file, re.IGNORECASE)
|
|
|
|
|
21 |
]
|
22 |
examples = []
|
23 |
try:
|
|
|
30 |
continue
|
31 |
for slice in range(mel.get_number_of_slices()):
|
32 |
image = mel.audio_slice_to_image(slice)
|
33 |
+
assert (image.width == args.resolution
|
34 |
+
and image.height == args.resolution)
|
|
|
35 |
with io.BytesIO() as output:
|
36 |
image.save(output, format="PNG")
|
37 |
bytes = output.getvalue()
|
38 |
+
examples.extend([{
|
39 |
+
"image": {
|
40 |
+
"bytes": bytes
|
41 |
+
},
|
42 |
+
"audio_file": audio_file,
|
43 |
+
"slice": slice,
|
44 |
+
}])
|
|
|
|
|
45 |
finally:
|
46 |
ds = Dataset.from_pandas(
|
47 |
pd.DataFrame(examples),
|
48 |
+
features=Features({
|
49 |
+
"image": Image(),
|
50 |
+
"audio_file": Value(dtype="string"),
|
51 |
+
"slice": Value(dtype="int16"),
|
52 |
+
}),
|
|
|
|
|
53 |
)
|
54 |
dsd = DatasetDict({"train": ds})
|
55 |
dsd.save_to_disk(os.path.join(args.output_dir))
|
|
|
59 |
|
60 |
if __name__ == "__main__":
|
61 |
parser = argparse.ArgumentParser(
|
62 |
+
description=
|
63 |
+
"Create dataset of Mel spectrograms from directory of audio files.")
|
64 |
parser.add_argument("--input_dir", type=str)
|
65 |
parser.add_argument("--output_dir", type=str, default="data")
|
66 |
parser.add_argument("--resolution", type=int, default=256)
|
audiodiffusion/__init__.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PIL import Image
|
2 |
+
from torch import cuda
|
3 |
+
from diffusers import DDPMPipeline
|
4 |
+
|
5 |
+
from .mel import Mel
|
6 |
+
|
7 |
+
VERSION = "1.0.1"
|
8 |
+
|
9 |
+
|
10 |
+
class AudioDiffusion:
|
11 |
+
|
12 |
+
def __init__(self,
|
13 |
+
model_id="teticio/audio-diffusion-256",
|
14 |
+
resolution=256,
|
15 |
+
cuda=cuda.is_available()):
|
16 |
+
"""Class for generating audio using Denoising Diffusion Probabilistic Models.
|
17 |
+
|
18 |
+
Args:
|
19 |
+
model_id (String): name of model (local directory or Hugging Face Hub)
|
20 |
+
resolution (int): size of square mel spectrogram in pixels
|
21 |
+
cuda (bool): use CUDA?
|
22 |
+
"""
|
23 |
+
self.mel = Mel(x_res=resolution, y_res=resolution)
|
24 |
+
self.model_id = model_id
|
25 |
+
self.ddpm = DDPMPipeline.from_pretrained(self.model_id)
|
26 |
+
if cuda:
|
27 |
+
self.ddpm.to("cuda")
|
28 |
+
|
29 |
+
def generate_spectrogram_and_audio(self):
|
30 |
+
"""Generate random mel spectrogram and convert to audio.
|
31 |
+
|
32 |
+
Returns:
|
33 |
+
PIL Image: mel spectrogram
|
34 |
+
(float, array): sample rate and raw audio
|
35 |
+
"""
|
36 |
+
images = self.ddpm(output_type="numpy")["sample"]
|
37 |
+
images = (images * 255).round().astype("uint8").transpose(0, 3, 1, 2)
|
38 |
+
image = Image.fromarray(images[0][0])
|
39 |
+
audio = self.mel.image_to_audio(image)
|
40 |
+
return image, (self.mel.get_sample_rate(), audio)
|
{src → audiodiffusion}/mel.py
RENAMED
@@ -1,4 +1,5 @@
|
|
1 |
import warnings
|
|
|
2 |
warnings.filterwarnings('ignore')
|
3 |
|
4 |
import librosa
|
@@ -7,6 +8,7 @@ from PIL import Image
|
|
7 |
|
8 |
|
9 |
class Mel:
|
|
|
10 |
def __init__(
|
11 |
self,
|
12 |
x_res=256,
|
@@ -16,6 +18,16 @@ class Mel:
|
|
16 |
hop_length=512,
|
17 |
top_db=80,
|
18 |
):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
self.x_res = x_res
|
20 |
self.y_res = y_res
|
21 |
self.sr = sample_rate
|
@@ -28,17 +40,40 @@ class Mel:
|
|
28 |
self.y = None
|
29 |
|
30 |
def load_audio(self, audio_file):
|
|
|
|
|
|
|
|
|
|
|
31 |
self.y, _ = librosa.load(audio_file, mono=True)
|
32 |
|
33 |
def get_number_of_slices(self):
|
|
|
|
|
|
|
|
|
|
|
34 |
return len(self.y) // self.slice_size
|
35 |
|
36 |
def get_sample_rate(self):
|
|
|
|
|
|
|
|
|
|
|
37 |
return self.sr
|
38 |
|
39 |
def audio_slice_to_image(self, slice):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
S = librosa.feature.melspectrogram(
|
41 |
-
y=self.y[self.slice_size * slice
|
42 |
sr=self.sr,
|
43 |
n_fft=self.n_fft,
|
44 |
hop_length=self.hop_length,
|
@@ -46,19 +81,24 @@ class Mel:
|
|
46 |
fmax=self.fmax,
|
47 |
)
|
48 |
log_S = librosa.power_to_db(S, ref=np.max, top_db=self.top_db)
|
49 |
-
bytedata = (
|
50 |
-
|
51 |
-
).astype(np.uint8)
|
52 |
image = Image.frombytes("L", log_S.shape, bytedata.tobytes())
|
53 |
return image
|
54 |
|
55 |
def image_to_audio(self, image):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
bytedata = np.frombuffer(image.tobytes(), dtype="uint8").reshape(
|
57 |
-
(image.width, image.height)
|
58 |
-
)
|
59 |
log_S = bytedata.astype("float") * self.top_db / 255 - self.top_db
|
60 |
S = librosa.db_to_power(log_S)
|
61 |
audio = librosa.feature.inverse.mel_to_audio(
|
62 |
-
S, sr=self.sr, n_fft=self.n_fft, hop_length=self.hop_length
|
63 |
-
)
|
64 |
return audio
|
|
|
1 |
import warnings
|
2 |
+
|
3 |
warnings.filterwarnings('ignore')
|
4 |
|
5 |
import librosa
|
|
|
8 |
|
9 |
|
10 |
class Mel:
|
11 |
+
|
12 |
def __init__(
|
13 |
self,
|
14 |
x_res=256,
|
|
|
18 |
hop_length=512,
|
19 |
top_db=80,
|
20 |
):
|
21 |
+
"""Class to convert audio to mel spectrograms and vice versa.
|
22 |
+
|
23 |
+
Args:
|
24 |
+
x_res (int): x resolution of spectrogram (time)
|
25 |
+
y_res (int): y resolution of spectrogram (frequency bins)
|
26 |
+
sample_rate (int): sample rate of audio
|
27 |
+
n_fft (int): number of Fast Fourier Transforms
|
28 |
+
hop_length (int): hop length (a higher number is recommended for lower than 256 y_res)
|
29 |
+
top_db (int): loudest in decibels
|
30 |
+
"""
|
31 |
self.x_res = x_res
|
32 |
self.y_res = y_res
|
33 |
self.sr = sample_rate
|
|
|
40 |
self.y = None
|
41 |
|
42 |
def load_audio(self, audio_file):
|
43 |
+
"""Load audio.
|
44 |
+
|
45 |
+
Args:
|
46 |
+
file (str): must be a file on disk due to Librosa limitation
|
47 |
+
"""
|
48 |
self.y, _ = librosa.load(audio_file, mono=True)
|
49 |
|
50 |
def get_number_of_slices(self):
|
51 |
+
"""Get number of slices in audio.
|
52 |
+
|
53 |
+
Returns:
|
54 |
+
int: number of spectograms audio can be sliced into
|
55 |
+
"""
|
56 |
return len(self.y) // self.slice_size
|
57 |
|
58 |
def get_sample_rate(self):
|
59 |
+
"""Get sample rate:
|
60 |
+
|
61 |
+
Returns:
|
62 |
+
int: sample rate of audio
|
63 |
+
"""
|
64 |
return self.sr
|
65 |
|
66 |
def audio_slice_to_image(self, slice):
|
67 |
+
"""Convert slice of audio to spectrogram.
|
68 |
+
|
69 |
+
Args:
|
70 |
+
slice (int): slice number of audio to convert (out of get_number_of_slices())
|
71 |
+
|
72 |
+
Returns:
|
73 |
+
PIL Image: grayscale image of x_res x y_res
|
74 |
+
"""
|
75 |
S = librosa.feature.melspectrogram(
|
76 |
+
y=self.y[self.slice_size * slice:self.slice_size * (slice + 1)],
|
77 |
sr=self.sr,
|
78 |
n_fft=self.n_fft,
|
79 |
hop_length=self.hop_length,
|
|
|
81 |
fmax=self.fmax,
|
82 |
)
|
83 |
log_S = librosa.power_to_db(S, ref=np.max, top_db=self.top_db)
|
84 |
+
bytedata = (((log_S + self.top_db) * 255 / self.top_db).clip(0, 255) +
|
85 |
+
0.5).astype(np.uint8)
|
|
|
86 |
image = Image.frombytes("L", log_S.shape, bytedata.tobytes())
|
87 |
return image
|
88 |
|
89 |
def image_to_audio(self, image):
|
90 |
+
"""Converts spectrogram to audio.
|
91 |
+
|
92 |
+
Args:
|
93 |
+
image (PIL Image): x_res x y_res grayscale image
|
94 |
+
|
95 |
+
Returns:
|
96 |
+
audio (array): raw audio
|
97 |
+
"""
|
98 |
bytedata = np.frombuffer(image.tobytes(), dtype="uint8").reshape(
|
99 |
+
(image.width, image.height))
|
|
|
100 |
log_S = bytedata.astype("float") * self.top_db / 255 - self.top_db
|
101 |
S = librosa.db_to_power(log_S)
|
102 |
audio = librosa.feature.inverse.mel_to_audio(
|
103 |
+
S, sr=self.sr, n_fft=self.n_fft, hop_length=self.hop_length)
|
|
|
104 |
return audio
|
notebooks/test-mel.ipynb
CHANGED
@@ -30,8 +30,8 @@
|
|
30 |
"metadata": {},
|
31 |
"outputs": [],
|
32 |
"source": [
|
33 |
-
"from
|
34 |
-
"from
|
35 |
]
|
36 |
},
|
37 |
{
|
@@ -178,7 +178,7 @@
|
|
178 |
"name": "python",
|
179 |
"nbconvert_exporter": "python",
|
180 |
"pygments_lexer": "ipython3",
|
181 |
-
"version": "3.
|
182 |
},
|
183 |
"toc": {
|
184 |
"base_numbering": 1,
|
|
|
30 |
"metadata": {},
|
31 |
"outputs": [],
|
32 |
"source": [
|
33 |
+
"from IPython.display import Audio\n",
|
34 |
+
"from audiodiffusion.mel import Mel"
|
35 |
]
|
36 |
},
|
37 |
{
|
|
|
178 |
"name": "python",
|
179 |
"nbconvert_exporter": "python",
|
180 |
"pygments_lexer": "ipython3",
|
181 |
+
"version": "3.10.4"
|
182 |
},
|
183 |
"toc": {
|
184 |
"base_numbering": 1,
|
notebooks/test-model.ipynb
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
requirements-lock.txt
CHANGED
@@ -2,6 +2,9 @@ absl-py==1.2.0
|
|
2 |
accelerate==0.12.0
|
3 |
aiohttp==3.8.1
|
4 |
aiosignal==1.2.0
|
|
|
|
|
|
|
5 |
appdirs==1.4.4
|
6 |
argon2-cffi==21.3.0
|
7 |
argon2-cffi-bindings==21.2.0
|
@@ -10,12 +13,19 @@ async-timeout==4.0.2
|
|
10 |
attrs==22.1.0
|
11 |
audioread==3.0.0
|
12 |
backcall==0.2.0
|
|
|
|
|
13 |
beautifulsoup4==4.11.1
|
14 |
bleach==5.0.1
|
|
|
15 |
cachetools==5.2.0
|
16 |
certifi==2022.6.15
|
17 |
cffi==1.15.1
|
18 |
charset-normalizer==2.1.1
|
|
|
|
|
|
|
|
|
19 |
datasets==2.4.0
|
20 |
debugpy==1.6.3
|
21 |
decorator==5.1.1
|
@@ -24,14 +34,23 @@ diffusers==0.2.4
|
|
24 |
dill==0.3.5.1
|
25 |
entrypoints==0.4
|
26 |
executing==0.10.0
|
|
|
27 |
fastjsonschema==2.16.1
|
|
|
28 |
filelock==3.8.0
|
|
|
29 |
frozenlist==1.3.1
|
30 |
fsspec==2022.7.1
|
31 |
ftfy==6.1.1
|
|
|
|
|
32 |
google-auth==2.11.0
|
33 |
google-auth-oauthlib==0.4.6
|
|
|
34 |
grpcio==1.47.0
|
|
|
|
|
|
|
35 |
huggingface-hub==0.9.0
|
36 |
idna==3.3
|
37 |
importlib-metadata==4.12.0
|
@@ -48,13 +67,20 @@ jupyter-console==6.4.4
|
|
48 |
jupyter-core==4.11.1
|
49 |
jupyterlab-pygments==0.2.2
|
50 |
jupyterlab-widgets==3.0.2
|
|
|
51 |
librosa==0.9.2
|
|
|
52 |
llvmlite==0.39.0
|
53 |
lxml==4.9.1
|
54 |
Markdown==3.4.1
|
|
|
55 |
MarkupSafe==2.1.1
|
|
|
56 |
matplotlib-inline==0.1.6
|
|
|
|
|
57 |
mistune==2.0.4
|
|
|
58 |
multidict==6.0.2
|
59 |
multiprocess==0.70.13
|
60 |
nbclient==0.6.7
|
@@ -65,9 +91,11 @@ notebook==6.4.12
|
|
65 |
numba==0.56.0
|
66 |
numpy==1.22.4
|
67 |
oauthlib==3.2.0
|
|
|
68 |
packaging==21.3
|
69 |
pandas==1.4.3
|
70 |
pandocfilters==1.5.0
|
|
|
71 |
parso==0.8.3
|
72 |
pexpect==4.8.0
|
73 |
pickleshare==0.7.5
|
@@ -83,11 +111,19 @@ pyarrow==9.0.0
|
|
83 |
pyasn1==0.4.8
|
84 |
pyasn1-modules==0.2.8
|
85 |
pycparser==2.21
|
|
|
|
|
|
|
|
|
86 |
Pygments==2.13.0
|
|
|
|
|
87 |
pyparsing==3.0.9
|
88 |
pyrsistent==0.18.1
|
89 |
python-dateutil==2.8.2
|
|
|
90 |
pytz==2022.2.1
|
|
|
91 |
PyYAML==6.0
|
92 |
pyzmq==23.2.1
|
93 |
qtconsole==5.3.1
|
@@ -97,14 +133,21 @@ requests==2.28.1
|
|
97 |
requests-oauthlib==1.3.1
|
98 |
resampy==0.4.0
|
99 |
responses==0.18.0
|
|
|
|
|
100 |
rsa==4.9
|
101 |
scikit-learn==1.1.2
|
102 |
scipy==1.9.0
|
|
|
103 |
Send2Trash==1.8.0
|
104 |
six==1.16.0
|
|
|
|
|
105 |
SoundFile==0.10.3.post1
|
106 |
soupsieve==2.3.2.post1
|
107 |
stack-data==0.4.0
|
|
|
|
|
108 |
tensorboard==2.10.0
|
109 |
tensorboard-data-server==0.6.1
|
110 |
tensorboard-plugin-wit==1.8.1
|
@@ -113,6 +156,7 @@ threadpoolctl==3.1.0
|
|
113 |
tinycss2==1.1.1
|
114 |
tokenizers==0.12.1
|
115 |
toml==0.10.2
|
|
|
116 |
torch==1.12.1
|
117 |
torchvision==0.13.1
|
118 |
tornado==6.2
|
@@ -120,9 +164,16 @@ tqdm==4.64.0
|
|
120 |
traitlets==5.3.0
|
121 |
transformers==4.21.1
|
122 |
typing_extensions==4.3.0
|
|
|
|
|
|
|
123 |
urllib3==1.26.12
|
|
|
|
|
|
|
124 |
wcwidth==0.2.5
|
125 |
webencodings==0.5.1
|
|
|
126 |
Werkzeug==2.2.2
|
127 |
widgetsnbextension==3.6.1
|
128 |
xxhash==3.0.0
|
|
|
2 |
accelerate==0.12.0
|
3 |
aiohttp==3.8.1
|
4 |
aiosignal==1.2.0
|
5 |
+
altair==4.2.0
|
6 |
+
analytics-python==1.4.0
|
7 |
+
anyio==3.6.1
|
8 |
appdirs==1.4.4
|
9 |
argon2-cffi==21.3.0
|
10 |
argon2-cffi-bindings==21.2.0
|
|
|
13 |
attrs==22.1.0
|
14 |
audioread==3.0.0
|
15 |
backcall==0.2.0
|
16 |
+
backoff==1.10.0
|
17 |
+
bcrypt==4.0.0
|
18 |
beautifulsoup4==4.11.1
|
19 |
bleach==5.0.1
|
20 |
+
blinker==1.5
|
21 |
cachetools==5.2.0
|
22 |
certifi==2022.6.15
|
23 |
cffi==1.15.1
|
24 |
charset-normalizer==2.1.1
|
25 |
+
click==8.1.3
|
26 |
+
commonmark==0.9.1
|
27 |
+
cryptography==37.0.4
|
28 |
+
cycler==0.11.0
|
29 |
datasets==2.4.0
|
30 |
debugpy==1.6.3
|
31 |
decorator==5.1.1
|
|
|
34 |
dill==0.3.5.1
|
35 |
entrypoints==0.4
|
36 |
executing==0.10.0
|
37 |
+
fastapi==0.81.0
|
38 |
fastjsonschema==2.16.1
|
39 |
+
ffmpy==0.3.0
|
40 |
filelock==3.8.0
|
41 |
+
fonttools==4.37.1
|
42 |
frozenlist==1.3.1
|
43 |
fsspec==2022.7.1
|
44 |
ftfy==6.1.1
|
45 |
+
gitdb==4.0.9
|
46 |
+
GitPython==3.1.27
|
47 |
google-auth==2.11.0
|
48 |
google-auth-oauthlib==0.4.6
|
49 |
+
gradio==3.1.7
|
50 |
grpcio==1.47.0
|
51 |
+
h11==0.12.0
|
52 |
+
httpcore==0.15.0
|
53 |
+
httpx==0.23.0
|
54 |
huggingface-hub==0.9.0
|
55 |
idna==3.3
|
56 |
importlib-metadata==4.12.0
|
|
|
67 |
jupyter-core==4.11.1
|
68 |
jupyterlab-pygments==0.2.2
|
69 |
jupyterlab-widgets==3.0.2
|
70 |
+
kiwisolver==1.4.4
|
71 |
librosa==0.9.2
|
72 |
+
linkify-it-py==1.0.3
|
73 |
llvmlite==0.39.0
|
74 |
lxml==4.9.1
|
75 |
Markdown==3.4.1
|
76 |
+
markdown-it-py==2.1.0
|
77 |
MarkupSafe==2.1.1
|
78 |
+
matplotlib==3.5.3
|
79 |
matplotlib-inline==0.1.6
|
80 |
+
mdit-py-plugins==0.3.0
|
81 |
+
mdurl==0.1.2
|
82 |
mistune==2.0.4
|
83 |
+
monotonic==1.6
|
84 |
multidict==6.0.2
|
85 |
multiprocess==0.70.13
|
86 |
nbclient==0.6.7
|
|
|
91 |
numba==0.56.0
|
92 |
numpy==1.22.4
|
93 |
oauthlib==3.2.0
|
94 |
+
orjson==3.8.0
|
95 |
packaging==21.3
|
96 |
pandas==1.4.3
|
97 |
pandocfilters==1.5.0
|
98 |
+
paramiko==2.11.0
|
99 |
parso==0.8.3
|
100 |
pexpect==4.8.0
|
101 |
pickleshare==0.7.5
|
|
|
111 |
pyasn1==0.4.8
|
112 |
pyasn1-modules==0.2.8
|
113 |
pycparser==2.21
|
114 |
+
pycryptodome==3.15.0
|
115 |
+
pydantic==1.9.2
|
116 |
+
pydeck==0.8.0b1
|
117 |
+
pydub==0.25.1
|
118 |
Pygments==2.13.0
|
119 |
+
Pympler==1.0.1
|
120 |
+
PyNaCl==1.5.0
|
121 |
pyparsing==3.0.9
|
122 |
pyrsistent==0.18.1
|
123 |
python-dateutil==2.8.2
|
124 |
+
python-multipart==0.0.5
|
125 |
pytz==2022.2.1
|
126 |
+
pytz-deprecation-shim==0.1.0.post0
|
127 |
PyYAML==6.0
|
128 |
pyzmq==23.2.1
|
129 |
qtconsole==5.3.1
|
|
|
133 |
requests-oauthlib==1.3.1
|
134 |
resampy==0.4.0
|
135 |
responses==0.18.0
|
136 |
+
rfc3986==1.5.0
|
137 |
+
rich==12.5.1
|
138 |
rsa==4.9
|
139 |
scikit-learn==1.1.2
|
140 |
scipy==1.9.0
|
141 |
+
semver==2.13.0
|
142 |
Send2Trash==1.8.0
|
143 |
six==1.16.0
|
144 |
+
smmap==5.0.0
|
145 |
+
sniffio==1.2.0
|
146 |
SoundFile==0.10.3.post1
|
147 |
soupsieve==2.3.2.post1
|
148 |
stack-data==0.4.0
|
149 |
+
starlette==0.19.1
|
150 |
+
streamlit==1.12.2
|
151 |
tensorboard==2.10.0
|
152 |
tensorboard-data-server==0.6.1
|
153 |
tensorboard-plugin-wit==1.8.1
|
|
|
156 |
tinycss2==1.1.1
|
157 |
tokenizers==0.12.1
|
158 |
toml==0.10.2
|
159 |
+
toolz==0.12.0
|
160 |
torch==1.12.1
|
161 |
torchvision==0.13.1
|
162 |
tornado==6.2
|
|
|
164 |
traitlets==5.3.0
|
165 |
transformers==4.21.1
|
166 |
typing_extensions==4.3.0
|
167 |
+
tzdata==2022.2
|
168 |
+
tzlocal==4.2
|
169 |
+
uc-micro-py==1.0.1
|
170 |
urllib3==1.26.12
|
171 |
+
uvicorn==0.18.3
|
172 |
+
validators==0.20.0
|
173 |
+
watchdog==2.1.9
|
174 |
wcwidth==0.2.5
|
175 |
webencodings==0.5.1
|
176 |
+
websockets==10.3
|
177 |
Werkzeug==2.2.2
|
178 |
widgetsnbextension==3.6.1
|
179 |
xxhash==3.0.0
|
requirements.txt
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
-
# for Hugging Face Spaces
|
2 |
torch
|
3 |
numpy
|
4 |
Pillow
|
5 |
-
diffusers
|
6 |
librosa
|
7 |
datasets
|
8 |
gradio
|
|
|
|
|
|
1 |
torch
|
2 |
numpy
|
3 |
Pillow
|
4 |
+
diffusers>=0.2.4
|
5 |
librosa
|
6 |
datasets
|
7 |
gradio
|
8 |
+
streamlit
|
setup.cfg
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[metadata]
|
2 |
+
name = audiodiffusion
|
3 |
+
version = attr: audiodiffusion.VERSION
|
4 |
+
description = Generate Mel spectrogram dataset from directory of audio files.
|
5 |
+
long_description = file: README.md
|
6 |
+
license = GPL3
|
7 |
+
classifiers =
|
8 |
+
Programming Language :: Python :: 3
|
9 |
+
|
10 |
+
[options]
|
11 |
+
zip_safe = False
|
12 |
+
packages = audiodiffusion
|
13 |
+
install_requires =
|
14 |
+
torch
|
15 |
+
numpy
|
16 |
+
Pillow
|
17 |
+
diffusers>=0.2.4
|
18 |
+
librosa
|
19 |
+
datasets
|
setup.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
|
3 |
+
from setuptools import setup
|
4 |
+
|
5 |
+
if __name__ == "__main__":
|
6 |
+
setup()
|
streamlit_app.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from io import BytesIO
|
2 |
+
import streamlit as st
|
3 |
+
import soundfile as sf
|
4 |
+
from librosa.util import normalize
|
5 |
+
|
6 |
+
from audiodiffusion import AudioDiffusion
|
7 |
+
|
8 |
+
audio_diffusion = AudioDiffusion()
|
9 |
+
|
10 |
+
if __name__ == "__main__":
|
11 |
+
st.header("Audio Diffusion")
|
12 |
+
st.markdown("Generate audio using Huggingface diffusers.\
|
13 |
+
This takes about 20 minutes without a GPU, so why not make yourself a cup of tea in the meantime?"
|
14 |
+
)
|
15 |
+
if st.button("Generate"):
|
16 |
+
st.markdown("Generating...")
|
17 |
+
image, (sample_rate,
|
18 |
+
audio) = audio_diffusion.generate_spectrogram_and_audio()
|
19 |
+
st.image(image, caption="Mel spectrogram")
|
20 |
+
buffer = BytesIO()
|
21 |
+
sf.write(buffer, normalize(audio), sample_rate, format="WAV")
|
22 |
+
st.audio(buffer, format="audio/wav")
|
src/train_unconditional.py → train_unconditional.py
RENAMED
@@ -24,8 +24,9 @@ from torchvision.transforms import (
|
|
24 |
ToTensor,
|
25 |
)
|
26 |
from tqdm.auto import tqdm
|
|
|
27 |
|
28 |
-
from mel import Mel
|
29 |
|
30 |
logger = get_logger(__name__)
|
31 |
|
@@ -65,7 +66,8 @@ def main(args):
|
|
65 |
"UpBlock2D",
|
66 |
),
|
67 |
)
|
68 |
-
noise_scheduler = DDPMScheduler(num_train_timesteps=1000,
|
|
|
69 |
optimizer = torch.optim.AdamW(
|
70 |
model.parameters(),
|
71 |
lr=args.learning_rate,
|
@@ -74,20 +76,17 @@ def main(args):
|
|
74 |
eps=args.adam_epsilon,
|
75 |
)
|
76 |
|
77 |
-
augmentations = Compose(
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
]
|
84 |
-
)
|
85 |
|
86 |
if args.dataset_name is not None:
|
87 |
if os.path.exists(args.dataset_name):
|
88 |
-
dataset = load_from_disk(args.dataset_name,
|
89 |
-
|
90 |
-
]
|
91 |
else:
|
92 |
dataset = load_dataset(
|
93 |
args.dataset_name,
|
@@ -110,20 +109,18 @@ def main(args):
|
|
110 |
|
111 |
dataset.set_transform(transforms)
|
112 |
train_dataloader = torch.utils.data.DataLoader(
|
113 |
-
dataset, batch_size=args.train_batch_size, shuffle=True
|
114 |
-
)
|
115 |
|
116 |
lr_scheduler = get_scheduler(
|
117 |
args.lr_scheduler,
|
118 |
optimizer=optimizer,
|
119 |
num_warmup_steps=args.lr_warmup_steps,
|
120 |
-
num_training_steps=(len(train_dataloader) * args.num_epochs)
|
121 |
-
|
122 |
)
|
123 |
|
124 |
model, optimizer, train_dataloader, lr_scheduler = accelerator.prepare(
|
125 |
-
model, optimizer, train_dataloader, lr_scheduler
|
126 |
-
)
|
127 |
|
128 |
ema_model = EMAModel(
|
129 |
getattr(model, "module", model),
|
@@ -139,13 +136,14 @@ def main(args):
|
|
139 |
run = os.path.split(__file__)[-1].split(".")[0]
|
140 |
accelerator.init_trackers(run)
|
141 |
|
142 |
-
mel = Mel(x_res=args.resolution,
|
|
|
|
|
143 |
|
144 |
global_step = 0
|
145 |
for epoch in range(args.num_epochs):
|
146 |
-
progress_bar = tqdm(
|
147 |
-
|
148 |
-
)
|
149 |
progress_bar.set_description(f"Epoch {epoch}")
|
150 |
|
151 |
if epoch < args.start_epoch:
|
@@ -168,13 +166,14 @@ def main(args):
|
|
168 |
timesteps = torch.randint(
|
169 |
0,
|
170 |
noise_scheduler.num_train_timesteps,
|
171 |
-
(bsz,),
|
172 |
device=clean_images.device,
|
173 |
).long()
|
174 |
|
175 |
# Add noise to the clean images according to the noise magnitude at each timestep
|
176 |
# (this is the forward diffusion process)
|
177 |
-
noisy_images = noise_scheduler.add_noise(clean_images, noise,
|
|
|
178 |
|
179 |
with accelerator.accumulate(model):
|
180 |
# Predict the noise residual
|
@@ -209,11 +208,10 @@ def main(args):
|
|
209 |
if epoch % args.save_model_epochs == 0 or epoch == args.num_epochs - 1:
|
210 |
pipeline = DDPMPipeline(
|
211 |
unet=accelerator.unwrap_model(
|
212 |
-
ema_model.averaged_model if args.use_ema else model
|
213 |
-
),
|
214 |
scheduler=noise_scheduler,
|
215 |
)
|
216 |
-
|
217 |
# save the model
|
218 |
if args.push_to_hub:
|
219 |
try:
|
@@ -238,17 +236,16 @@ def main(args):
|
|
238 |
)["sample"]
|
239 |
|
240 |
# denormalize the images and save to tensorboard
|
241 |
-
images_processed = (
|
242 |
-
|
243 |
-
|
244 |
accelerator.trackers[0].writer.add_images(
|
245 |
-
"test_samples", images_processed, epoch
|
246 |
-
)
|
247 |
for _, image in enumerate(images_processed):
|
248 |
audio = mel.image_to_audio(Image.fromarray(image[0]))
|
249 |
accelerator.trackers[0].writer.add_audio(
|
250 |
f"test_audio_{_}",
|
251 |
-
audio,
|
252 |
epoch,
|
253 |
sample_rate=mel.get_sample_rate(),
|
254 |
)
|
@@ -258,7 +255,8 @@ def main(args):
|
|
258 |
|
259 |
|
260 |
if __name__ == "__main__":
|
261 |
-
parser = argparse.ArgumentParser(
|
|
|
262 |
parser.add_argument("--local_rank", type=int, default=-1)
|
263 |
parser.add_argument("--dataset_name", type=str, default=None)
|
264 |
parser.add_argument("--dataset_config_name", type=str, default=None)
|
@@ -303,8 +301,7 @@ if __name__ == "__main__":
|
|
303 |
help=(
|
304 |
"Whether to use mixed precision. Choose"
|
305 |
"between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10."
|
306 |
-
"and an Nvidia Ampere GPU."
|
307 |
-
),
|
308 |
)
|
309 |
parser.add_argument("--hop_length", type=int, default=512)
|
310 |
parser.add_argument("--from_pretrained", type=str, default=None)
|
|
|
24 |
ToTensor,
|
25 |
)
|
26 |
from tqdm.auto import tqdm
|
27 |
+
from librosa.util import normalize
|
28 |
|
29 |
+
from audiodiffusion.mel import Mel
|
30 |
|
31 |
logger = get_logger(__name__)
|
32 |
|
|
|
66 |
"UpBlock2D",
|
67 |
),
|
68 |
)
|
69 |
+
noise_scheduler = DDPMScheduler(num_train_timesteps=1000,
|
70 |
+
tensor_format="pt")
|
71 |
optimizer = torch.optim.AdamW(
|
72 |
model.parameters(),
|
73 |
lr=args.learning_rate,
|
|
|
76 |
eps=args.adam_epsilon,
|
77 |
)
|
78 |
|
79 |
+
augmentations = Compose([
|
80 |
+
Resize(args.resolution, interpolation=InterpolationMode.BILINEAR),
|
81 |
+
CenterCrop(args.resolution),
|
82 |
+
ToTensor(),
|
83 |
+
Normalize([0.5], [0.5]),
|
84 |
+
])
|
|
|
|
|
85 |
|
86 |
if args.dataset_name is not None:
|
87 |
if os.path.exists(args.dataset_name):
|
88 |
+
dataset = load_from_disk(args.dataset_name,
|
89 |
+
args.dataset_config_name)["train"]
|
|
|
90 |
else:
|
91 |
dataset = load_dataset(
|
92 |
args.dataset_name,
|
|
|
109 |
|
110 |
dataset.set_transform(transforms)
|
111 |
train_dataloader = torch.utils.data.DataLoader(
|
112 |
+
dataset, batch_size=args.train_batch_size, shuffle=True)
|
|
|
113 |
|
114 |
lr_scheduler = get_scheduler(
|
115 |
args.lr_scheduler,
|
116 |
optimizer=optimizer,
|
117 |
num_warmup_steps=args.lr_warmup_steps,
|
118 |
+
num_training_steps=(len(train_dataloader) * args.num_epochs) //
|
119 |
+
args.gradient_accumulation_steps,
|
120 |
)
|
121 |
|
122 |
model, optimizer, train_dataloader, lr_scheduler = accelerator.prepare(
|
123 |
+
model, optimizer, train_dataloader, lr_scheduler)
|
|
|
124 |
|
125 |
ema_model = EMAModel(
|
126 |
getattr(model, "module", model),
|
|
|
136 |
run = os.path.split(__file__)[-1].split(".")[0]
|
137 |
accelerator.init_trackers(run)
|
138 |
|
139 |
+
mel = Mel(x_res=args.resolution,
|
140 |
+
y_res=args.resolution,
|
141 |
+
hop_length=args.hop_length)
|
142 |
|
143 |
global_step = 0
|
144 |
for epoch in range(args.num_epochs):
|
145 |
+
progress_bar = tqdm(total=len(train_dataloader),
|
146 |
+
disable=not accelerator.is_local_main_process)
|
|
|
147 |
progress_bar.set_description(f"Epoch {epoch}")
|
148 |
|
149 |
if epoch < args.start_epoch:
|
|
|
166 |
timesteps = torch.randint(
|
167 |
0,
|
168 |
noise_scheduler.num_train_timesteps,
|
169 |
+
(bsz, ),
|
170 |
device=clean_images.device,
|
171 |
).long()
|
172 |
|
173 |
# Add noise to the clean images according to the noise magnitude at each timestep
|
174 |
# (this is the forward diffusion process)
|
175 |
+
noisy_images = noise_scheduler.add_noise(clean_images, noise,
|
176 |
+
timesteps)
|
177 |
|
178 |
with accelerator.accumulate(model):
|
179 |
# Predict the noise residual
|
|
|
208 |
if epoch % args.save_model_epochs == 0 or epoch == args.num_epochs - 1:
|
209 |
pipeline = DDPMPipeline(
|
210 |
unet=accelerator.unwrap_model(
|
211 |
+
ema_model.averaged_model if args.use_ema else model),
|
|
|
212 |
scheduler=noise_scheduler,
|
213 |
)
|
214 |
+
|
215 |
# save the model
|
216 |
if args.push_to_hub:
|
217 |
try:
|
|
|
236 |
)["sample"]
|
237 |
|
238 |
# denormalize the images and save to tensorboard
|
239 |
+
images_processed = ((images *
|
240 |
+
255).round().astype("uint8").transpose(
|
241 |
+
0, 3, 1, 2))
|
242 |
accelerator.trackers[0].writer.add_images(
|
243 |
+
"test_samples", images_processed, epoch)
|
|
|
244 |
for _, image in enumerate(images_processed):
|
245 |
audio = mel.image_to_audio(Image.fromarray(image[0]))
|
246 |
accelerator.trackers[0].writer.add_audio(
|
247 |
f"test_audio_{_}",
|
248 |
+
normalize(audio),
|
249 |
epoch,
|
250 |
sample_rate=mel.get_sample_rate(),
|
251 |
)
|
|
|
255 |
|
256 |
|
257 |
if __name__ == "__main__":
|
258 |
+
parser = argparse.ArgumentParser(
|
259 |
+
description="Simple example of a training script.")
|
260 |
parser.add_argument("--local_rank", type=int, default=-1)
|
261 |
parser.add_argument("--dataset_name", type=str, default=None)
|
262 |
parser.add_argument("--dataset_config_name", type=str, default=None)
|
|
|
301 |
help=(
|
302 |
"Whether to use mixed precision. Choose"
|
303 |
"between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >= 1.10."
|
304 |
+
"and an Nvidia Ampere GPU."),
|
|
|
305 |
)
|
306 |
parser.add_argument("--hop_length", type=int, default=512)
|
307 |
parser.add_argument("--from_pretrained", type=str, default=None)
|