aax2wav - convert audible aax files to wav, mp3, ogg, ...

I will not offer a tool for download here - I am not sure about legal stuff.

You will read about analysis and ways to convert audible aax files to wav (and if you want to mp3 or anything using ffmpeg) and so remove the DRM restrictions.

This will only work with an installed Audible Manager on Windows - neither iTunes nor Windows Media Player or any Virtual CD-Burner are required. This is only good for legally purchased stuff from Audible, not for anything else!

What you need: C/C++ knowledge, programming skills, Audible Manager installed

Ok, let's go

  1. Create some C/C++ project - I just created a Console Application
  2. dynamically load "AAXSDKWin.dll" that comes with the Audible Manager like this:
    HMODULE hDll = LoadLibrary(L"c:\\Program Files (x86)\\Audible\\Bin\\AAXSDKWin.dll");
  3. define some function types:
    typedef signed int __cdecl T_AAXOpenFileWinW(BYTE** paaxhandle, LPCWSTR fname);
    typedef signed int __cdecl T_AAXCloseFile(BYTE* aaxhandle);
    typedef int __cdecl T_AAXAuthenticateWin(BYTE *aaxhandle);
    typedef signed int __cdecl T_AAXSeek(BYTE* aaxhandle, int);
    typedef signed int __cdecl T_AAXGetAudioChannelCount(BYTE* aaxhandle, DWORD *channels);
    typedef signed int __cdecl T_AAXGetSampleRate(BYTE *aaxhandle, DWORD *samplerate);
    typedef signed int __cdecl T_AAXGetEncodedAudio(BYTE* aaxhandle, BYTE* buf, DWORD bufsize, DWORD* length);
    typedef int __cdecl T_AAXDecodePCMFrame(BYTE* aaxhandle, BYTE* buf, DWORD bufsize, BYTE* decbuf, DWORD decbufsize, DWORD *length);
  4. Get pointers to those functions:
    T_AAXOpenFileWinW *AAXOpenFileWinW = (T_AAXOpenFileWinW*)GetProcAddress(hDll, "AAXOpenFileWinW");
    T_AAXCloseFile *AAXCloseFile = (T_AAXCloseFile*)GetProcAddress(hDll, "AAXCloseFile");
    T_AAXAuthenticateWin *AAXAuthenticateWin = (T_AAXAuthenticateWin*)GetProcAddress(hDll, "AAXAuthenticateWin");
    T_AAXSeek *AAXSeek = (T_AAXSeek*)GetProcAddress(hDll, "AAXSeek");
    T_AAXGetAudioChannelCount *AAXGetAudioChannelCount = (T_AAXGetAudioChannelCount*)GetProcAddress(hDll, "AAXGetAudioChannelCount");

    T_AAXGetSampleRate *AAXGetSampleRate = (T_AAXGetSampleRate*)GetProcAddress(hDll, "AAXGetSampleRate");
    T_AAXGetEncodedAudio *AAXGetEncodedAudio = (T_AAXGetEncodedAudio*)GetProcAddress(hDll, "AAXGetEncodedAudio");T_AAXDecodePCMFrame *AAXDecodePCMFrame = (T_AAXDecodePCMFrame*)GetProcAddress(hDll, "AAXDecodePCMFrame");
  5. need some variables:
    BYTE *aaxhandle; //no malloc needed!
    DWORD encbufsize = 0x400;
    DWORD decbufsize = 0x400 * 200; //probably 4KB would be enough
    DWORD enclength = 0;
    DWORD declength = 0;
    BYTE *encbuf = (BYTE*)malloc(encbufsize);
    BYTE *decbuf = (BYTE*)malloc(decbufsize);
    DWORD channels = 0;
    DWORD samplerate = 0;
    int error = 0; //all AAX functions return 0 if no error
  6. You will need a RIFF/WAV-header for the decoded PCM stream:
    struct WaveHeader
    BYTE RIFF[4]; // "RIFF"
    DWORD filesize; // filesize - 8
    BYTE WAVE[4]; // "WAVE"
    BYTE fmt[4]; // "fmt " (including space after fmt)
    DWORD data_hdrlen; // 16
    WORD fmt_type; // 1
    WORD num_channels; // AAXGetAudioChannelCount()
    DWORD sample_rate; // AAXGetSampleRate()
    DWORD bytes_per_second; // sample_rate * num_channels * 2
    WORD bytes_per_frame; // num_channels * 2
    WORD bits_per_sample; // 16
    BYTE DATA[4]; // "data"
    DWORD datasize;
    (AAXDecodePCMFrame() seems always to give 16 bit samples, so you can just take num_channels * 2 to calculate the bytes per frame and bytes per second)
  7. Call the AAX functions:
    error = AAXOpenFileWinW(&aaxhandle, L"myfile.aax");
    error = AAXGetAudioChannelCount(aaxhandle, &channels);
    error = AAXGetSampleRate(aaxhandle, &samplerate);
    error = AAXSeek(aaxhandle, 0);

    error = AAXAuthenticateWin(aaxhandle); //without this call decoding will fail!

    //create some wav file here and write some dummy header to it (to reserve the space)

    DWORD datalength = 0;
    do {
    error = AAXGetEncodedAudio(aaxhandle, encbuf, encbufsize, &enclength);
    error = AAXDecodePCMFrame(aaxhandle, encbuf, enclength, decbuf, decbufsize, &declength);
    datalength += declength;
    // write decbuf to wav file here
    } while(enclength > 0);

    error = AAXCloseFile(aaxhandle);
  8. Last: do some cleanup (memory freeing, fseek to beginning of file and write correct header with known file- and datasize, ...)
  9. Download ffmpeg and convert your wav file to mp3
    ffmpeg -i myfile.wav myfile.mp3