import types from '../types' import Tone from 'tone' import JSZip from 'jszip' import { sprintf } from 'sprintf-js' import * as draw from './lib/draw' import output from './lib/output' import spectrum from './lib/spectrum' import { requestAudioContext } from './lib' export const FRAME_LENGTH = 126 * 255 export const FRAME_STEP = Math.round(FRAME_LENGTH / 4) const _r = 8 const _i = 8 export { spectrum } // requestAudioContext(() => {}) export const loadBuffer = file => { return new Promise((resolve, reject) => { const url = URL.createObjectURL(file) let buffer = new Tone.Buffer( url, loadBuffer, err => { console.error('err', err) reject(err) } ) function loadBuffer() { URL.revokeObjectURL(url) resolve(buffer) } }) } export const loadPCM = (file) => { return new Promise((resolve, reject) => { // if we've already fetched this file... if (file.pcm) { return resolve(file) } loadBuffer(file).then(buffer => { const pcm = buffer._buffer.getChannelData(0) const sr = buffer._buffer.sampleRate if (! pcm) return reject() console.log(pcm.length, sr) resolve({ file, buffer, pcm, sr }) }) }) } export const renderFrames = (file, { frame_step=FRAME_STEP, frame_start=0, max=12 }) => dispatch => { return new Promise((resolve, reject) => { loadPCM(file).then((pcmProps) => { const { file, buffer, pcm, sr } = pcmProps dispatch({ type: types.wav2pix.load }) let frames = [] let count = 0 let _len = pcm.length - FRAME_LENGTH let offset = Math.round(_len * frame_start) for (; offset < _len && count < max; offset += frame_step, count += 1 ) { frames.push(render(pcm.slice(offset, offset+FRAME_LENGTH), sr, count)) } dispatch({ type: types.wav2pix.finish, message: 'Rendered ' + count + ' images' }) resolve({ pcm: pcmProps, frames }) }) }) } export const buildZip = (name, file, { frame_step=FRAME_STEP, frame_start=0, max=10000 }) => dispatch => { return new Promise((resolve, reject) => { loadPCM(file).then(({ buffer, pcm, sr }) => { dispatch({ type: types.wav2pix.load }) const zip = new JSZip() const zip_folder = zip.folder("wav2pix_" + name); let steps = (pcm.length - FRAME_LENGTH) / frame_step console.log(steps) let count = 0 let _len = pcm.length - FRAME_LENGTH let offset = Math.round(_len * frame_start) for (; offset < _len && count < max; offset += frame_step, count += 1 ) { if ((count % 10) === 0) { dispatch({ type: types.wav2pix.progress, progress: { i: count / max * 6, n: 6 } }) } render(pcm.slice(offset, offset+FRAME_LENGTH), sr, count, zip_folder) } // dispatch event dispatch({ type: types.wav2pix.finish, message: 'Rendered ' + count + ' images' }) zip.generateAsync({ type: "blob" }).then(content => { dispatch({ type: types.wav2pix.zip, size: content.size }) // FileSaver.saveAs(content, "wav2pix_" + name + ".zip") resolve({ zip: content, filename: "wav2pix_" + name + ".zip", count }) }) }) }) } function render(pcm, sr, count, zip){ const fft = spectrum.toSpectrum(pcm, sr) // console.log('render', fft) // const pcm_rev = pcm.slice().reverse() // const spec_rev = spectrum.toSpectrum(pcm_rev, spec.sr) const { canvas, imageData } = draw.raw_spectrum(fft, 0, 256, 0, 256, _r, _i) if (zip) { const name = sprintf('frame_%05d.png', count) const dataURL = canvas.toDataURL("image/png") zip.file(name, dataURL.split(',')[1], {base64: true}) } return { fft, canvas, imageData } }