Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move streams module to streams package, reduce per file line count
- Loading branch information
Paul R. Adams
committed
Jan 7, 2018
1 parent
ac98570
commit a41ce25
Showing
5 changed files
with
187 additions
and
178 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
"""create a batch of pcm streams by interfacing with iTunes | ||
""" | ||
|
||
import os | ||
import time | ||
import subprocess | ||
import json | ||
|
||
|
||
from clamm import config | ||
from clamm import util | ||
|
||
|
||
TMPSTREAM = os.path.join(config["path"]["wav"], "temp.wav") | ||
|
||
|
||
def dial_itunes(artist, album): | ||
"""run apple script and attempt to uniquely locate the | ||
artist/album pair. | ||
""" | ||
|
||
util.printr("talking to iTunes...") | ||
util.generate_playlist(artist, album) | ||
time.sleep(2) # allow time to build playlist | ||
osa_prog = os.path.join(config["path"]["osa"], "play") | ||
subprocess.Popen(['osascript', osa_prog]) | ||
|
||
|
||
def main(listing): | ||
"""a program for batch streaming a ``json`` listing of albums | ||
from iTunes to raw pcm files via ``shairport-sync``. | ||
iTunes is controlled using macos' built-in ``osascript`` tool and | ||
simple javascript request templates. | ||
When the listings have finished streaming, the pcm files (streams) | ||
can be processed by ``stream2tracks`` and converted from streams | ||
to a collection of flac tracks. | ||
""" | ||
|
||
util.printr("Begin streams.from_listing...") | ||
|
||
# fetch the album listing | ||
with open(listing) as fptr: | ||
batch = json.load(fptr) | ||
|
||
# iterate over albums in the listing | ||
for key, val in batch.items(): | ||
|
||
util.start_shairport(TMPSTREAM) | ||
|
||
artist, album = val['artist'], val['album'] | ||
wav = "{}; {}.wav".format(artist, album) | ||
wav_path = os.path.join(config["path"]["wav"], wav) | ||
|
||
util.printr("{} --> begin listing2streams stream of {}..." | ||
.format(time.ctime(), wav)) | ||
|
||
dial_itunes(artist, album) | ||
|
||
monitor = util.SimpleState(TMPSTREAM) | ||
while not monitor.get_state("startd"): | ||
time.sleep(1) | ||
|
||
util.printr("Stream successfully started, " | ||
" now waiting for finish (one dot per minute)...") | ||
|
||
while not monitor.get_state("finishd"): | ||
time.sleep(1) | ||
|
||
util.printr("Stream successfully finished.") | ||
|
||
os.rename(TMPSTREAM, wav_path) | ||
|
||
util.printr("Batch successfully finished.") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
""" | ||
Convert a large audio wav file (album length, i.e. > 30 minutes typically) | ||
into a series of videos consisting of the audio synchronized with images of the | ||
spectrogram. | ||
""" | ||
import os | ||
import sys | ||
import multiprocessing as mp | ||
import subprocess | ||
|
||
import tqdm | ||
import numpy as np | ||
import librosa.core | ||
import librosa.display | ||
import librosa.feature | ||
import matplotlib.pyplot as plt | ||
plt.switch_backend("agg") | ||
|
||
SAMPLERATE = 44.1e3 # samples/sec | ||
WAVPATH = sys.argv[1] | ||
BASENAME = os.path.basename(WAVPATH).replace(".wav", "") | ||
ROOT = "/mnt/nfs-share/music/data" | ||
FRAMEROOT = ROOT + "/frames/" + BASENAME | ||
DURATION = 20 # | ||
NUMPROC = 8 | ||
FFTFREQ = librosa.fft_frequencies(sr=SAMPLERATE) | ||
F_MAX = np.max(FFTFREQ) | ||
N_FFT = 2048 | ||
N_HOP = int(1.0 / 4 * N_FFT) | ||
FILETIME = librosa.core.get_duration(filename=WAVPATH) | ||
NFRAME = int(FILETIME) / DURATION # allow truncation | ||
DUMPFILE = "data.npy" | ||
FPS = 5 | ||
|
||
|
||
def single_image(argtuple): | ||
y, i_frame, i_second = argtuple | ||
fractional_second = float(i_second) / FPS | ||
abs_index = i_frame * DURATION * FPS + i_second | ||
time = DURATION*i_frame + fractional_second | ||
titlestr = "%s - file time %0.2f seconds" % (BASENAME, time) | ||
|
||
# display the spectrogram | ||
plt.figure(figsize=(18, 8)) | ||
librosa.display.specshow( | ||
y, x_axis='time', y_axis='mel', sr=SAMPLERATE, hop_length=N_HOP) | ||
|
||
plt.vlines( | ||
fractional_second, 0, F_MAX, | ||
linestyles='dashed', colors='w', alpha=0.6) | ||
|
||
plt.title(titlestr) | ||
plt.savefig(FRAMEROOT + "/%05d.png" % (abs_index)) | ||
plt.tight_layout() | ||
plt.close() | ||
|
||
|
||
def main(): | ||
""" main | ||
""" | ||
|
||
pbar = tqdm.tqdm(total=NFRAME) | ||
pool = mp.Pool(NUMPROC) | ||
init = False | ||
if not os.path.exists(FRAMEROOT): | ||
os.makedirs(FRAMEROOT) | ||
|
||
for i_frame in range(10, NFRAME): | ||
# load the audio | ||
x, sr = librosa.core.load( | ||
WAVPATH, sr=SAMPLERATE, | ||
offset=DURATION * i_frame, duration=DURATION) | ||
|
||
# compute the spectrogram | ||
x = librosa.power_to_db( | ||
librosa.feature.melspectrogram( | ||
y=x, hop_length=N_HOP, n_fft=N_FFT, sr=SAMPLERATE), | ||
ref=np.max) | ||
|
||
if not init: | ||
f_mean = np.sum(x, axis=1) | ||
init = True | ||
else: | ||
f_mean += np.sum(x, axis=1) | ||
|
||
# loop updates | ||
pbar.update(1) | ||
pool.map( | ||
single_image, | ||
[(x, i_frame, i_second) for i_second in range(FPS*DURATION)]) | ||
|
||
np.save(BASENAME + 'f_mean.npy', f_mean) | ||
pbar.close() | ||
|
||
subprocess.call([ | ||
"ffmpeg", '-r', '5', '-i', FRAMEROOT + '%05d.png', '-i', WAVPATH, | ||
'-shortest', '-c:v', 'libx264', '-c:a', 'aac', '-strict', '-2', | ||
'-pix_fmt', 'yuv420p', '-crf', '23', '-r', '5', '-y', | ||
ROOT + "/videos/" + BASENAME + '.mp4']) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Oops, something went wrong.