SpringOne Americas

Private Events

Blogs

View all Blogs >>
  • Andrew Glover

    Co-author of "Continuous Integration"

    Every once in a while the topic of code coverage surfaces, which more»

  • Stuart Halloway

    CEO of Relevance

    Programmers coming to functional languages for the first time cannot imagine life without variables. I address this head-on in the more»

  • Richard Monson-Haefel

    VP of Developer Relations, Curl Inc.

    more»

  • Neal Ford

    Application Architect at ThoughtWorks, Inc.

    The lowly whiteboard is one of my favorite tools for design work on projects: you can stand in front of it as a group, you can easily play... more»

  • Michael Nygard

    Agile technology leader and dynamicist

    Sizing, Danish Style Folks in telecommunications and operations research have used Erl more»

  • Matt Raible

    Creator of AppFuse and author of Spring Live

    It's been three weeks since I joined the realm of the unemployed. Fortunately, I more»

  • Alex Miller

    Sr. Engineer with Terracotta Inc.

    Or maybe that should be “a bit of final advice”. :) There was a more»

  • Vladimir Vivien

    Software Engineer / Consultant

    I finally downloaded the latest JDK 6 u 10 (download) recently. This is a significant re more»

  • Scott Leberknight

    Chief Architect at Near Infinity

    Re nae Bair's post on The Ranting Rubyis more»

  • Graeme Rocher

    Project Lead of the Grails Project & CTO of G2One

    Those crazy guys over at the Grails podcast interviewed me about various things ranging from being part of more»

  • Ted Neward

    Enterprise, Virtual Machine and Language Wonk

    Dustin Campbell, a self-professed "IDE guy", is speaking at the .NET Developer's Association of Redmond this evening, on the future of... more»

  • Pratik Patel

    Enterprise Architect

    There's been a 'backlash' of sorts brewing in the Java developer community over the past 2 years. From talking to my developer buddies around... more»

  • Howard Lewis Ship

    Creator of Tapestry and HiveMind

    Seems like the Mac has a huge number of RSS readers. For a while I was using Vienna, but it stopped working after a recent update (no blogs... more»

  • Mike Levin

    Software Developer specializing in Web2.0 websites

    (photo from more»

  • Brian Pontarelli

    Founder of Inversoft

    Just figured out how to get git tab completion working in zsh on a Mac. Turns out that the completion scripts use a bunch of extra git... more»

  • Erik Doernenburg

    Principal Consultant @ Thoughtworks

    If you are somebody who writes code you probably know that moment when you look at some code you didn’t write, or some code you wrote a... more»

  • Kirk Knoernschild

    Software Developer & Mentor

    more»

  • Brian Goetz

    Author of Java Concurrency in Practice

    I live in an AT&T-free state, so I have not had access to the cult that is iPhone. But recently, in preparation for AT&T moving... more»

  • Matthew Bass

    Software Developer & Entrepreneur

    Can Sphinx and foxy fixtures place nicely together? Due to the way Sphinx indexing works, foxy fixtures will often slow down the indexing... more»

  • Jason Rudolph

    Author of Getting Started with Grails

    I had the more»

  • Ryan Shriver

    Business and Technology Consulting

    more»

  • Nathaniel Schutta

    Author, speaker, software engineer focused on user interface design.

    Today we learned something important, the NTSB announced the more»

  • Jeff Brown

    SpringSource Engineering And Professional Services - Groovy and Grails Developer

    Strange enough title.Let's start with a hypothetical conversation between a geeky developer and his much less geeky wife: more»

  • Jared Richardson

    Agile coach and co-author of Ship It

    Jurgen Appelo has an ongoing interview series on his blog. He's published a lot of very smart people and I'm honored to squeak in too! ;) more»

  • David Bock

    Principal Consultant, CodeSherpas Inc.

    I have been setting up a rock-solid server cluster for a client and ran into an interesting issue trying to install Phusion Passenger onto... more»

  • Pramod Sadalage

    Co-author of "Refactoring Databases:Evolutionary Database Development"

    Consider this Hibernate mapping @Column(name = "qReferenceId") public Long getQReferenceId() { return qReferenceId; more»

  • Craig Walls

    Author of Spring in Action

    At one time not too long ago, I wasn't a big fan of annotations. But then I let my guard down and even started liking them. But now I'm... more»

  • Kenneth Kousen

    President of Kousen IT, Inc.

    In this entry in my “Making Swing Groovy” series, I want to talk about threading issues. Specifically, more»

  • Venkat Subramaniam

    Founder of Agile Developer, Inc.

    I wrote a four part article for Java World on creating DSLs in Java and Groovy. For your convenience, I decided to list the links to those... more»

  • Jason Harwig

    Senior Software Engineer at Near Infinity

    The most popular entry I've written at Near Infinity has been the more»

  • John Heintz

    Principal Consultant with New Aspects of Software

    In a recent discussion interview questions came up, here's my favorite one.To set some context this question is designed to gauge the abst more»

  • Mark Johnson

    Director of Consulting at CGI

    At the Columbus NFJS show held on July 25-27th during one of the BOF sessions Dave Bock, Scott Davis and I discussed unit tests vs functional... more»

  • Joseph Nusairat

    Author of Beginning JBoss Seam & Co-Author of Beginning Groovy & Grails

    Well i am assuming Apress has the most random site in the world at times.But today only they have our recent book, Beginning Groovy & Grai more»

  • Keith Donald

    Lead of Spring Web and Creator of Spring Web Flow

    I am pleased to announce that Developing Rich Web Applications with Spring, a three-day bootcamp lead by SpringSource engineers on web... more»

  • Pete Behrens

    Organizational Agility Coach

    Marti nig & Associates Methods & Tools group recentl more»

  • Brian Sam-Bodden

    Java author, Ruby geek and Open Source Advocate

    In this installment we are going to build the Dashboard page of the Tempo application. T more»

  • Mark Fisher

    Spring Integration Lead

    In my recent post, I had mentio more»

  • Ron Bodkin

    Chief Software Architect, Quantcast

    I'm looking forward to speaking at The Rich Web Experience conference in San Jose next month. The event runs from September 7th through 9th.... more»

  • Mark Goodwin

    Web Application Security Specialist

    We've already looked at one of the two big problems posed by anti DNS pinning on Java applets; because there's rebinding on the applet and... more»

  • Scott Davis

    Author of "Groovy Recipes" & TDD Expert

    Every time I see a live show at the Denver Botanic more»

  • Romain Guy

    Java User Interface expert.

    more»

  • Ramnivas Laddad

    Author of AspectJ in Action, Principal at SpringSource

    InfoQ.com has published my AOP myths and realities talk recorded at a No Fluff Just Stuff conference. InfoQ.com founded by Floyd Marine more»

  • David Geary

    Author of Graphic Java and co-author of Core JSF

    The 2006 NFJS tour kicked off t more»

  • Kito Mann

    Editor-in-chief of JSF Central and the author of JSF in Action

    I miss the latest.integration keyword from ivy.... more»

  • Jason Hunter

    Author of Java Servlet Programming

    I just posted the JDOM 1.1 release for download. This release includes about 20 improvements and bug fixes. more»

The Music Project

Posted by: Neal Ford on 08/29/2008
I was talking to my friend Brian Goetz recently, and he reminded me of a blog entry he posted a while back. He's digitizing his entire music collection, and he's done all the research. This is appealing to me because I recently switched over to zero reliance on the shiny plastic disks once I've ripped them. All my music consumption is now electronic, mostly via iPod (the car was the last frontier, and now that's switched over as well). I have a large-ish CD collection (~1500 CDs), so translating them to electronic form is no small feat. And I only have to do it once for the rest of my life.

Based on my conversations with Brian, I realized the following:
  • Ripping and encoding are completely separate activities
  • The most important thing is to get a reliable, error corrected rip
  • You don't want to get stuck with a proprietary format (as much as I love Apple, I don't want my music collection tied up in one of their formats forever)
  • Lossless is the way to go, so that you don't loose any data in this process
  • Cross-encoding allows you to rip your music in a "core" format and selectively support proprietary formats and reduced file sizes (and lossiness)
His original entry is about his Windows and Linux based infrastructure. I replicated his same setup (with minor differences) on the Mac.

A Home

First, you need a home for all these files. I recently got a network attached storage device to hold our growing collection of digital photos. I'm my family's tech support, and if anything ever happens to those photos, I'm a dead man! After doing a lot of research on quality, Mac compatibility (my household is 100% Mac now), I ended up with the NETGEAR RND4250 ReadyNAS, which comes with 500 GB of storage (2 mirrored 500 GB drives), with a capacity of 2 TB. I ended up bumping it up to a TB when I realized how big the combination of music + pictures would be, and the Netgear handled it beautifully.

Ripping

I didn't realize this, but most rippers don't take advantage of the error correction bits on the CD, and they are wimps: they give up way too easily. The trick is to find a ripper that is relentless and tries its hardest to get all the bits off the CD. The ripper/encoder I ended up using is Max, which supports Leopard in it's latest (allegedly) unstable form, and previous Mac OS X versions in it's previous (stable) release. I caveat "unstable" because I used it a lot and it was rock solid for me on Leopard. One of the nice things about Max is its support for different rippers: fast & carefree, or paranoid. The latter is the one I want, based on the cdparanoia project. You can configure this ripper to never give up until it gets a clean read of the disk. Several of my CDs trundled for 6-10 hours before Max finally reported success, including a couple that I'd given up for dead.

Encoding

OK, so now I have a good rip, I need to encode it (this post makes it sound like separate steps, but Max handles both for you). As I stated earlier, I don't want to get trapped by a specific format. I ended up (like Brian) choosing FLAC. FLAC is a open standard encoding for music that offers lossless compression, which is what I wanted. The FLAC spec also allows for more aggressive compression without loss of data, depending on your patience. It's designed to take longer to encode but have no impact on playback time. I choose the most aggressive because I have time, hardware (a MacPro with 4 processors), and I want to conserve space if possible. But, iTunes (which is how I play and sync my music) doesn't support FLAC. Max to the rescue: it will let you do parallel encoding. I set Max up to encode the ripped music files to both lossless FLAC and lossless MP4 (Apple's format). The only downside is that it won't allow you to choose different directories for the encoding. The FLAC files I'm placing on a RAID mirrored network-attached storage drive (remember, I never want to do this again!). So, I ended up writing a little Rake file to handle automatically moving the files from one place to another. I rip them all to the RAID drive, then let the script move them (preserving directories) to the other. The script is here, if anyone wants it (no warranty expressed or implied -- you'll have to change all the directories, and if you use this to erase your hard drive I'll shed a tear for you, but might just laugh).
task :copy do
count = 0
skipped = 0
FileList["**/*.m4a"].each do |f|
artist, album = recording_info_based_on f
if File.exist? "#{DEST}/#{artist}/#{album}/#{File.basename(f)}"
puts "\tsomething is amiss; I'm skipping: #{f}"
skipped += 1
else
FileUtils.mkdir "#{DEST}/#{artist}" unless File.exist? "#{DEST}/#{artist}"
FileUtils.mkdir "#{DEST}/#{artist}/#{album}" unless File.exist? "#{DEST}/#{artist}/#{album}"
puts "#{artist} - #{album} - #{File.basename(f)}"
count += 1
FileUtils.cp f,"#{DEST}/#{artist}/#{album}"
end
end
puts "copied #{count} files\nskipped #{skipped} files"
end

def recording_info_based_on filename
File.expand_path(filename) =~ /.*\/(.*)\/(.*)\/.*/
return $1, $2
end

I also made a rake task to report any that ended up missing from the original FLAC directories to the AAC files (just in case something went amiss during a copy process, or I screwed up and deleted something by mistake). I want to make sure that the convenience Apple-format files match the canonical source (the FLAC) files. So, this is the "missing" rake task:

task :report_missings do
count = 0
FileList["**/*.flac"].each do |f|
artist, album = recording_info_based_on f
dest_file_name = File.basename(f).sub /flac/, "m4a"
unless File.exist? "#{DEST}/#{artist}/#{album}/#{dest_file_name}"
puts "missing #{f.sub /\.flac/, ''}"
count += 1
end
end
puts "found #{count} missing files"
end

Result

It took me about 2 months of ripping while I'm around my computer, running 2 computers (my laptop and desktop) in parallel. In the end, though, I ended up with 453 GB of music files, the FLAC ones safely tucked away on a mirrored drive and the M4A ones on my desktop, ready to be synced to my iPod (or a subset of them, anyway). Now, when I get a new CD, I rip it using Max to the NAS and either copy the files by hand (if it's just one CD) or use the Rake file to move lots en-masse. Storage is now dirt cheap, and I've leveraged almost a terabyte of it keeping the music files in 2 formats. I also recently bought a portable 500 GB drive so that I can keep all my music with me on the road. It's a copy of the desktop M4A files, but it's easy just to mirror the Music directory from the desktop to the portable drive.

I achieved my goal: an open archival format that I hope will be around for a very long time, and a convenience version for the way I happen to consume them today. And the shiny disks? I put them all in binders, so that if I ever need one of them (or it's sleeve), I can rummage around in the (mostly) alphabetical CD volumes. I didn't put a huge amount of effort creating an expandable storage that makes it easy to keep them in strict order because that would take lots of effort and it isn't something I expect to have to do often. If it turns out I got back to them all the time, I'll invest the time then.
be the first to rate this blog


About Neal Ford

Neal Ford is an Application Architect for ThoughtWorks. He is an architect, designer, and developer of applications, instructional materials, magazine articles, and video/DVD presentations. Neal is also the author of Developing with Delphi: Object-Oriented Techniques (Prentice Hall PTR, 1996), JBuilder 3 Unleashed (SAMS Publishing, 1999), and Art of Java Web Development (Manning, 2003). His language proficiencies include Java, C#/.NET, Ruby, Object Pascal, C++, and C. Neal’s primary consulting focus is the design and construction of large-scale enterprise applications. He is also an internationally acclaimed speaker, having spoken at over 30 developers’ conferences worldwide.