广西快乐十分最新开奖:Anaconda Limousine: the guitar parts

June 17th, 2012. Tagged: ffmpeg, JavaScript, Music, tools

I'm part of a band that has an album out now. I know, right? (links: excuse-for-a-site, amazon, itunes).

I wanted to put up all the songs on the site, but seems like there's a little dissonance in the band whether this is a good idea. Plan B: 30s samples. Like the bigwigs do on Amazon and iTunes.

But while their samples are random, a band can do a better job in picking parts that are representative of the overall sound. I though - let me pick my solo stuff only as an exercise. So there: Anaconda Limousine: the guitar parts.

I wanted to use command-line ffmpeg, of course, because all music software is like Photoshop to me, just can't figure out what's going on with so much UI. Turned out I needed sox too.

And then I want to use HTML5 Audio to play the samples.

I thought: an audio sprite would be a good idea, put all samples in one file, then JS can update the UI depending on which sample is playing. And I thought might be neat to have the JS turn the volume up and down to fade in/out the samples, like iTunes does. Turns out sox is doing this so nicely, that I let it do it.

Samples

I started by listening to the songs and taking notes with song #, start and end.

var slices = [
  {song: 1,  start:   8, end:  21},
  {song: 1,  start: 301, end: 323}, // from 3:01 to 3:23
  {song: 1,  start: 405, end:   0}, // 0 means till the end
  {song: 2,  start:   0, end:  30},
  {song: 2,  start: 305, end: 318},
  {song: 2,  start: 330, end:   0},
  {song: 3,  start:   0, end:  20},
  {song: 3,  start: 333, end:   0},
  {song: 4,  start: 303, end:   0},
  {song: 5,  start:   0, end:  20},
  {song: 5,  start: 300, end: 333},
  {song: 7,  start:   0, end:  20},
  {song: 7,  start: 340, end:   0},
  {song: 8,  start:   0, end:  25},
  {song: 8,  start: 313, end:   0},
  {song: 9,  start: 155, end: 239},
  {song: 9,  start: 350, end:   0}
];

Start 0 means start from the beginning of the song, end 0 means go to the end.

The time format is optimized for easy typing (I was walking, typing in Notes app on the iPhone). Turned out I need to convert the times to seconds:

function secs(num) {
  if (num <= 60) {
    return 1 * num
  }
  num += '';
  return num[0] * 60 + num[1] * 10 + num[2] * 1;
}

And I need album meta data too, with name of the song, filename and duration:

 
var songs = [
  {name: "Virus",     fname: "01-virus",     duration: 436},
  {name: "Yesterday", fname: "02-yesterday", duration: 346},
  {name: "All for you", fname: "03-all4u",   duration: 404},
  {name: "Damage",    fname: "04-damage",    duration: 333},
  {name: "Everyday",  fname: "05-everyday",  duration: 444},
  {name: "Girl of mine", fname: "06-girlomine", duration: 338},
  {name: "Fool on the hill", fname: "07-fool",  duration: 413},
  {name: "Faultline", fname: "08-faultline", duration: 347},
  {name: "Parting is such sweet sorrow", 
                      fname: "09-parting",   duration: 420}
];

Ripping the album

In the interest of quality I wanted to work with WAV and then encode in m4a, ogg and mp3.

On TuneCore.com there's a nice step-by-step instruction how to rip a CD to WAV in iTunes, because it uses mp3 by default.

So then I had the files:

01-virus.wav
02-yesterday.wav
03-all4u.wav
04-damage.wav
05-everyday.wav
06-girl.wav
07-fool.wav
08-faultline.wav
09-parting.wav

Slicing and fading

I used ffmpeg to do the slicing, like for example the first sample:

$ ffmpeg -i 01-virus.wav -ss 5 -t 20 ff-0.wav

-ss is start time and -t is duration. As you see instead of starting at 8 seconds (as described in the samples array) I start earlier. This is to give some more music for fade in/out.

For fade in/out I used sox. I didn't know this awesome command line tool existed, but found out while searching how to combine wav files (I know for mp3 you can just `cat`)

I don't want to fade in when the sample starts at the beginning. Or fade out then the sample happens to end at the end of the song. sox takes fade-in duration (or 0 for no fade in), stop time (0 for till the end of the file/sample) and fade out duration (again 0 is no fade out)

I used 3 secods fade in, 4 fade out. The sox commands are one of:

$ sox in.wav out.wav fade 3 0 0
$ sox in.wav out.wav fade 3 0 4
$ sox in.wav out.wav fade 0 0 4

And since I have all the configs in JS, JS makes perfect sense to generate the commands. Hope you can make sense of the comments:

var fadein = 3;
var fadeout = 4;
var merge = ['sox'];
slices.forEach(function(s, index){
  var ff = ['ffmpeg -i'];
  ff.push(songs[s.song - 1].fname  + '.wav'); // in file
  ff.push('-ss');
  ff.push(s.start ? secs(s.start) - fadein : 0); // start of the slice
  ff.push('-t');
  ff.push(!s.end ? 
      1000 : 
      secs(s.end) - secs(s.start) + fadein + fadeout); // end slice
  ff.push('ff-' + index  + '.wav'); // out file
  
  var sox = ['sox'];
  sox.push('ff-' + index  + '.wav'); // in file
  sox.push('s-' + index  + '.wav'); // out file
  sox.push('fade');
  sox.push(s.start ? fadein : 0); // fade in, unless it;s the beginning of the song
  sox.push(0); // till the end of the slice
  sox.push(s.end ? fadeout : 0); // fade out unless it's The End
    
  console.log(ff.join(' '));
  console.log(sox.join(' '));
  
  merge.push('s-' + index  + '.wav');
});
 
merge.push('_.wav');
console.log(merge.join(' '));

Running this gives me a bunch of commands:

ffmpeg -i 01-virus.wav -ss 5 -t 20 ff-0.wav
sox ff-0.wav s-0.wav fade 3 0 4
ffmpeg -i 01-virus.wav -ss 178 -t 29 ff-1.wav
sox ff-1.wav s-1.wav fade 3 0 4
[....]

sox s-0.wav s-1.wav s-2.wav s-3.wav [...] s-16.wav _.wav

2 for each sample (slice and fade) and one last one to merge all faded results. Nothing left to do but run the generated commands.

Save for Web

Final step is to convert the result _.wav to a web-ready format: m4a, ogg or mp3:

$ ffmpeg -i _.wav _.m4a
$ ffmpeg -i _.wav _.mp3
$ ffmpeg -i _.wav -acodec vorbis -aq 60 -strict experimental _.ogg

Turn it up!

Enjoy Anaconda Limousine: The Guitar Parts (ogg, m4a or mp3) with all samples in one file.

And come back later for the JS player part.

See you!

Tell your friends about this post: Facebook, Twitter, Google+

Sorry, comments disabled and hidden due to excessive spam.

Meanwhile, hit me up on twitter @stoyanstefanov


  • 76人参加高山滑雪跨界跨项选材测试 或进冬奥备战梯队 2019-05-18
  • 不是特效!上港队长一脚踢中海鸥 这脚法简直坑爹 2019-05-08
  • 新疆坚决打好污染防治攻坚战 2019-05-07
  • 高考在即,晋中市招生考试管理中心提醒广大考生及家长要把握好高考“四个趋势” 2019-04-25
  • 运城市在长三角招商引资149.9亿元 2019-04-08
  • 济南五胞胎雪虎宝宝亮相 四雌一雄萌态十足 2019-04-08
  • 去产能迎年中考 煤炭、钢铁企业债务问题依然存在 2019-04-07
  • 最高检等四部门出台意见 指导依法办理恐怖活动和极端主义犯罪案件 2019-04-07
  • 广州市黄埔区人民法院公告专栏 2019-03-28
  • 这个“海之宁”是个死抱着相对论旧谬误不放,疯狂反对科学新真理的跳梁“小丑”,这个跳梁“小丑”根本就不懂得尊重客观事实及其规律,总是无视、脱离、歪曲客观... 2019-03-22
  • 如何理解孔子这句话?北大教授胡军动情论生死 2019-03-21
  • 海外舆论关注中国最新军备 称赞习近平主席强军号令 2019-03-19
  • 女性之声——全国妇联 2019-03-19
  • 美司法部科米在希拉里邮件门调查中存在过失 2019-03-17
  • “四新”彰显党的十九大思想灵魂和精髓要义 2018-08-17
  • 196| 472| 668| 22| 550| 43| 470| 311| 731| 779|