Turn audio into a shareable video. forked from nypublicradio/audiogram

waveform.js 2.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. var probe = require("../lib/probe.js"),
  2. d3 = require("d3"),
  3. pcmStream = require("../lib/pcm.js");
  4. function getWaveform(filename, options, cb) {
  5. probe(filename, function(err, data) {
  6. if (err) {
  7. return cb(err);
  8. }
  9. if (options.maxDuration && options.maxDuration < data.duration) {
  10. return cb("Exceeds max duration of " + options.maxDuration + "s");
  11. }
  12. var stream = pcmStream(filename, {
  13. channels: options.channels
  14. }),
  15. samples = [];
  16. stream.on("data",function(sample, channel){
  17. // Average multiple channels
  18. if (channel > 0) {
  19. samples[samples.length - 1] = ((samples[samples.length - 1] * channel) + sample) / (channel + 1);
  20. } else {
  21. samples.push(sample);
  22. }
  23. });
  24. stream.on("error", cb);
  25. stream.on("end", function(output){
  26. var processed = processSamples(samples, Math.floor(data.duration * options.framesPerSecond), options.samplesPerFrame);
  27. console.log(processed[0]);
  28. return cb(null, processed);
  29. });
  30. });
  31. }
  32. function processSamples(samples, numFrames, samplesPerFrame) {
  33. // TODO spread out slop across frames
  34. var perFrame = Math.floor(samples.length / numFrames),
  35. perPoint = Math.floor(perFrame / samplesPerFrame),
  36. range = d3.range(samplesPerFrame),
  37. min = max = 0;
  38. var unadjusted = d3.range(numFrames).map(function(frame){
  39. var frameSamples = samples.slice(frame * perFrame, (frame + 1) * perFrame);
  40. return range.map(function(point){
  41. var pointSamples = frameSamples.slice(point * perPoint, (point + 1) * perPoint),
  42. localMin = localMax = 0;
  43. for (var i = 0, l = pointSamples.length; i < l; i++) {
  44. localMin = Math.min(localMin, pointSamples[i]);
  45. localMax = Math.max(localMax, pointSamples[i]);
  46. }
  47. min = Math.min(min, localMin);
  48. max = Math.max(max, localMax);
  49. return [localMin, localMax];
  50. });
  51. });
  52. console.log(unadjusted[0]);
  53. return unadjusted.map(function(frame){
  54. return frame.map(function(point){
  55. return [-point[0] / min, point[1] / max];
  56. });
  57. });
  58. }
  59. module.exports = getWaveform;