Created
December 5, 2019 21:02
-
-
Save mauritslamers/6015a256a2aa51689e3b8f9afd914a4d to your computer and use it in GitHub Desktop.
audacity rescue script nodejs with stereo support
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
// recover from audacity crash | |
// usage: | |
// node audacity_rescue.js [sourcedir] [result_file.wav] [mono|stereo] | |
// the mono or stereo option is optional, the default is mono. | |
// | |
// Description: | |
// This script will sort all files on modification date. | |
// If you create a backup, make sure you use `cp -a` to preserve the modification date | |
// or create a zip. | |
// The resulting file will pretend to be a wave file (because of the .wav extension), but | |
// is in fact a Audacity simple block file. You will have to open the resulting file with | |
// audacity and then export it as a normal file. | |
const fs = require('fs'); | |
const pathLib = require('path'); | |
const pj = pathLib.join; | |
const srcdirname = process.argv[2]; | |
const result_file = process.argv[3]; | |
const type = process.argv[4]; | |
if (!(srcdirname && result_file)) { | |
console.log("Need both a source dir and a target file"); | |
process.exit(1); | |
} | |
if (!type) type = 'mono'; | |
if (! (type === 'mono' || type === 'stereo')) { | |
console.log('invalid audio format'); | |
} | |
console.log('source dir name: ', srcdirname); | |
console.log('result_file', result_file); | |
// we need all files in the subdirectories of dirname | |
// sorted by date | |
const allFiles = []; | |
function readFiles (dir) { | |
const names = fs.readdirSync(dir); | |
names.forEach(n => { | |
const fullPath = pj(dir, n); | |
const stats = fs.statSync(fullPath); | |
if (stats.isDirectory()) { | |
readFiles(fullPath); | |
} | |
else { | |
if (pathLib.extname(n) === ".au") { | |
allFiles.push({ name: fullPath, time: stats.mtime.getTime()}) | |
} | |
} | |
}); | |
} | |
console.log('searching and sorting files by date'); | |
readFiles(srcdirname); | |
allFiles.sort( (a, b) => { | |
return a.time - b.time; | |
}); | |
if (type === 'stereo') { | |
console.log('writing result files'); | |
const f = pathLib.parse(result_file); | |
const left_fn = pathLib.join(f.root, f.dir, f.base + '_L' + f.ext); | |
const right_fn = pathLib.join(f.root, f.dir, f.base + '_R' + f.ext); | |
const fhL = fs.openSync(left_fn, 'w'); | |
const fhR = fs.openSync(right_fn, 'w'); | |
let targetPosL = 0; | |
let targetPosR = 0; | |
const numFiles = allFiles.length; | |
allFiles.forEach( (f, i) => { | |
console.log(`reading ${f.name} (${i} of ${numFiles})`); | |
const buf = fs.readFileSync(f.name); | |
const offset = (i === 0 || i === 1) ? 0: buf.readUInt16LE(4); | |
if (i % 2 === 0) { // assume left | |
targetPosL += fs.writeSync(fhL, buf, offset, buf.length-offset, targetPosL); | |
} | |
else { | |
// assume right | |
targetPosR += fs.writeSync(fhR, buf, offset, buf.length-offset, targetPosR); | |
} | |
}) | |
fs.closeSync(fhL); | |
fs.closeSync(fhR); | |
} | |
else { | |
// now merge all files in the result | |
console.log('writing result file'); | |
const fh = fs.openSync(result_file, 'w'); | |
let targetPos = 0; | |
const numFiles = allFiles.length; | |
allFiles.forEach( (f, i) => { | |
console.log(`reading ${f.name} (${i} of ${numFiles})`); | |
const buf = fs.readFileSync(f.name); | |
const offset = i === 0? 0: buf.readUInt16LE(4); | |
targetPos += fs.writeSync(fh, buf, offset, buf.length-offset, targetPos); | |
}); | |
fs.closeSync(fh); | |
} | |
console.log('Done'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi! Thanks so much for putting this together. Do you know if this would work with multiple tracks? I'm trying on a crashed project that has multiple tracks, and they do get appended but they are in a strange order.
Also, do I have to run this on all files in the
_data
folder, on only a certain subset?