Skip to content

Commit

Permalink
move streams module to streams package, reduce per file line count
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul R. Adams committed Jan 7, 2018
1 parent ac98570 commit a41ce25
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 178 deletions.
105 changes: 0 additions & 105 deletions clamm/plot_big_stft.py

This file was deleted.

79 changes: 79 additions & 0 deletions clamm/streams/from_listing.py
@@ -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()
103 changes: 103 additions & 0 deletions clamm/streams/plot_big_stft.py
@@ -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()

0 comments on commit a41ce25

Please sign in to comment.