Digitizing Cassette Tapes

So I’m trying to get some audio digitized off of tape. Unfortunately the old-school Audiograbber software that I used to use (uhh, circa 1998, when I was leaving high school) pulled the record-direct-to-MP3 feature out of their software. So, yeah, since I have a ton of RAM in my laptop (2 orders of magnitude more than I had back then!), I figured I’d just use Audacity and trade memory for time and record to uncompressed PCM, then compress. It’s a step backwards, but ho hum, that’s the rechtslage that we find ourselves in.

Of course, Audacity doesn’t come with an MP3 encoder due to royalty issues. And I didn’t really feel like downloading some random DLL from the site they link to in Brazil (where presumably the MPEG-LA doesn’t have much authority).

So I built LAME myself on Windows 8, using Microsoft Visual Studio 2012 Express, and a copy of NASM.

To get the build working, there were some tweaks that needed to be made to the Makefile.MSVC file that comes with the package. Since Audacity is a 32-bit executable, the tweaks tune it for a 32-bit output DLL.

First up, lib.exe command options at the top of the file:

MACHINE = /machine:I386
LIB_OPTS = /nologo $(MACHINE)

should be, adding Link Time Code Generation (ASLR and DEP get enabled by default, so you don’t need the /DYNAMICBASE /NXCOMPAT options):

MACHINE = /machine:X86
LIB_OPTS = /nologo $(MACHINE) /LTCG

There’s some detection of the Visual Studio 2012 environment variables you can add (you MUST use the uppercase version of the environment variable name, or nmake won’t resolve it!):

!	 ELSEIF "$(VISUALSTUDIOVERSION)" == "11.0"
!	  MESSAGE + using MSVC 11.0 32-Bit Compiler
!	  IF "$(CPU)" == "P1"
!	   MESSAGE + optimizing for Pentium (MMX) (may slow down PIII a few percent)
!	  ELSE
!	   MESSAGE + optimizing for Pentium II/III
!	  ENDIF

And then use the same sort of ELSEIF block to define some compiler optimizations:

!	ELSEIF "$(VISUALSTUDIOVERSION)" == "11.0"
CC_OPTS = /nologo /O2 /Ob2 /Oitxy /favor:blend /fp:precise /Qfast_transcendentals /Qpar /GL /GA /arch:SSE2

There’re two lines defining linker options that need to be changed from:

LN_OPTS = /nologo /opt:NOWIN98 /pdb:none
LN_DLL = /nologo /DLL /opt:NOWIN98

to:

LN_OPTS = /nologo /pdb:none /LTCG
LN_DLL = /nologo /DLL /LTCG

There’s the line defining the NASM command line to assemble certain objects, you need to change the “nasmw” command to be “nasm”, since that’s what the NASM executable is now called:

.nas.obj:
	@echo $<
	@nasm -f $(OFF) -i libmp3lame/i386/ -DWIN32 $< -o $@

Then I ran the whole thing with:

nmake -f Makefile.MSVC all

And get the following error:

--- COMMON FRONTEND STUFF UPTODATE ---

Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

libmp3lame-static.lib(psymodel.obj) : error LNK2001: unresolved external symbol
_static_assert_tab_mask_add_delta
.outputlame.exe : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: '"C:Program Files (x86)Microsoft Visual Studio 11.0
VCBINlink.EXE"' : return code '0x460'
Stop.

The offending code looks like this:

Which makes me hate the C preprocessor.

So I comment out the define's expansion. I guess it's useful, if those things ever have a size mismatch in the foreseeable future. The WTF-factor on that one feels pretty high, though, especially the preprocessor macro abuse and the fact that the two definitions are right next to each other, lending themselves to quick inspection. If they were cross-modules, or in separate files, I'd understand. (C needs to die, or learn from D)

Anyway, after that issue is removed, huzzah, it all builds:

--- COMMON FRONTEND STUFF UPTODATE ---

Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

Generating code
Finished generating code

--=* .outputlame.exe ready *=--

rtp.c
mp3rtp.c
Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

Generating code
Finished generating code

--=* .outputmp3rtp.exe ready *=--

   Creating library .outputlibmp3lame.lib and object .outputlibmp3lame.exp
Generating code
Finished generating code

--=* .outputlibmp3lame.dll ready *=--

BladeMP3EncDll.c
Microsoft (R) Windows (R) Resource Compiler Version 6.2.9200.16384
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library .outputlame_enc.lib and object .outputlame_enc.exp
Generating code
Finished generating code

--=* .outputlame_enc.dll ready *=--


--=* all uptodate *=--

And there you go! Now just copy the libmp3lame.dll file into Audacity's plugins directory, select it via the Audacity preferences, and it should work.

Update: Here's the Makefile.msvc.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.