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 $

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.

Bad Drivers

One of the things that Microsoft did in engineering the Windows 8 kernel was to eliminate and mitigate entire categories of kernel-mode memory exploits, by hardening the implementation with various new checks and removing code that would swallow multiple exceptions. The upside of this is that the kernel is more tamper-resistant. The downside (or upside, depending on how you look at it) is that buggy drivers now cause immediate kernel panics as soon as an offending operation is performed.

In other words, leaky, exploitable in-kernel drivers from days of old now cause the system to blue screen immediately when they do something wrong. This is actually the correct behavior and should help new driver devs catch problems early, but it also means my mid-2009 13″ MacBook Pro (model 5,5) has been blue screening like crazy ever since I installed Boot Camp 4.

It also means that, when these bugchecks are happening on Windows 8, they aren’t necessarily happening on Windows 7, or Vista, or XP. These could be points for investigation, by people wanting to develop exploits on those systems, because they would know exactly where the driver is doing something wrong in kernel memory.

Anyway, I got down and dirty and took a look at the minidumps being generated by the Boot Camp Services. There’s no official support for Windows 8 from Apple yet, but having drivers that are buggy on Windows 7 but that don’t immediately error out is probably also not a great thing.

Apple, take note, your Hardware Abstraction Layer driver is buggy:


Loading Dump File [C:WindowsMinidump