Hey,
I no longer use Mixxx or other software-based mixing (at least for the moment)
but figured someone here may be interested to know the AudioID binary blob in
a Traktor DJ playlist's entry is actually a base64-encoded visual thumbnail of
the track's WAV, squeezed to 512-pixels wide, with each 4-bit nybble
representing a volume. The image is mirrored vertically. I guess it's used as a
preview while tracks are deep-scanned.
I attached my source here, the thumbnail decoder function is at the end,
nmlEntry::SaveWAVThumbnail(), the rest is rubbish.
cheers,
-- p
// Native Instruments' Traktor DJ NML playlist decoder
// #include regex // not supported until gcc 4.9 ?
// #include tuple
/*
- RELEASE_DATE is optional
*/
#include wx/filename.h
#include wx/base64.h
#include wx/wfstream.h
#include wx/txtstrm.h
#include wx/sstream.h
#include wx/regex.h
#include Controller.h
#include TraktorDec.h
using namespace LX;
using namespace std;
enum FIELD_TYPES : int
{
FIELD_ILLEGAL = 0,
FIELD_STRING,
FIELD_INTEGER,
FIELD_DOUBLE, // front space-padding is ok
FIELD_UNIX_PATH,
FIELD_FILE_NAME,
FIELD_OS_PATH,
FIELD_OS_VOLUME,
FIELD_DATE, // /MM/DD
FIELD_MARKER_NAME, // { Cue | Beat Marker | Fade In | Fade Out } or { first moan | aha! | beat start | beat restart | restart | buildup start }
FIELD_ENC64,
FIELD_STRING_LIST // for CUEs
};
enum TAG_TYPES : int
{
TTYP_ARTIST = 0,
TTYP_AUDIO_ID,
TTYP_ID,
TTYP_LOCK,
TTYP_TRACK_TITLE,
TTYP_DIR,
TTYP_FILE,
TTYP_PATH,
TTYP_DISK_VOLUME,
TTYP_ALBUM,
TTYP_TRACK_NUMBER,
TTYP_BITRATE,
TTYP_COMMENT,
TTYP_GENRE,
TTYP_IMPORT_DATE,
TTYP_KEY_LYRICS,
TTYP_LAST_PLAYED,
TTYP_PLAYCOUNT,
TTYP_PLAYTIME,
TTYP_RANKING,
TTYP_RELEASE_DATE,
TTYP_BPM,
TTYP_BPM_QUALITY,
TTYP_PEAK_DB,
TTYP_PERCEIVED_DB,
TTYP_LABEL,
TTYP_POS,
TTYP_TYPE
};
static
void ConvVal(const wxString s, wxString *val_s)
{
wxASSERT(val_s);
*val_s = s;
}
static
void ConvVal(const wxString s, int *ip)
{
wxASSERT(ip);
long l = 0;
bool ok = s.ToLong(l);
wxASSERT(ok);
*ip = (int) l;
}
static
void ConvVal(const wxString s, double *dp)
{
wxASSERT(dp);
bool ok = s.ToDouble(dp);
wxASSERT(ok);
}
static
void ConvVal(const wxString s, wxDateTime *dt)
{
wxASSERT(dt);
bool ok = dt-ParseDate(s);
wxASSERT(ok);
}
// CTOR ---
TraktorDecoder::TraktorDecoder(Controller *controller)
{
wxASSERT(controller);
m_Controller = controller;
m_PlaylistEntries.clear();
m_TagToInfoMap.clear();
#if 0
m_TypeToConvMap =
{
{FIELD_STRING, {ValToStr}},
{FIELD_INTEGER, {ValToInt}},
{FIELD_DOUBLE, {ValToDouble}}, // may be space-padded in front
{FIELD_UNIX_PATH, {ValToStr}},
{FIELD_FILE_NAME, {ValToStr}},
{FIELD_OS_PATH, {ValToStr}},
{FIELD_OS_VOLUME, {ValToStr}},
{FIELD_DATE, {ValToDate}}, // /MM/DD
{FIELD_MARKER_NAME, {ValToStr}}, // { Cue | Beat Marker | Fade In | Fade Out } or { first moan | aha! | beat start | beat restart | restart | buildup start }
{FIELD_ENC64, {ValToStr}},
{FIELD_STRING_LIST, {ValToStr}}, // for CUEs
};
#endif
// use ___(unique)___ (R)aw string delimiter to use double-quotes within, even if preceding a ')'
bool ok = m_EntryRE.Compile(R___(.*?ENTRY(.*?)/ENTRY)___, wxRE_ADVANCED);
wxASSERT(ok m_EntryRE.IsValid());
ok = m_FieldRE.Compile(R___(.*? ([A-Z_]+)=(.*?))___, wxRE_ADVANCED);
wxASSERT(ok m_FieldRE.IsValid());
// few duplicate tags despite XML hierarchy, except for
// labels (list)
// title (duplicate)
m_TagToInfoMap =
{
{ARTIST, {TTYP_ARTIST, FIELD_STRING}},
{AUDIO_ID, {TTYP_AUDIO_ID, FIELD_ENC64}},
{ID, {TTYP_ID, FIELD_INTEGER}},
{LOCK, {TTYP_LOCK, FIELD_INTEGER}},
{TITLE, {TTYP_TRACK_TITLE, FIELD_STRING}},
{DIR, {TTYP_DIR, FIELD_UNIX_PATH}},
{FILE, {TTYP_FILE, FIELD_FILE_NAME}},
{PATH, {TTYP_PATH, FIELD_OS_PATH}},
{VOLUME, {TTYP_DISK_VOLUME, FIELD_OS_VOLUME}},
{ALBUM, {TTYP_ALBUM, FIELD_STRING}},
{TRACK, {TTYP_TRACK_NUMBER, FIELD_INTEGER}},
{BITRATE, {TTYP_BITRATE, FIELD_INTEGER}},
{COMMENT, {TTYP_COMMENT, FIELD_STRING}},
{GENRE, {TTYP_GENRE, FIELD_STRING}},
{IMPORT_DATE, {TTYP_IMPORT_DATE, FIELD_DATE}},
{KEY_LYRICS, {TTYP_KEY_LYRICS, FIELD_STRING}},
{LAST_PLAYED, {TTYP_LAST_PLAYED, FIELD_DATE}},
{PLAYCOUNT, {TTYP_PLAYCOUNT, FIELD_INTEGER}},
{PLAYTIME, {TTYP_PLAYTIME, FIELD_INTEGER}},
{RANKING, {TTYP_RANKING, FIELD_INTEGER}},
{RELEASE_DATE, {TTYP_RELEASE_DATE, FIELD_DATE}},
{BPM, {TTYP_BPM, FIELD_DOUBLE}},
{BPM_QUALITY, {TTYP_BPM_QUALITY, FIELD_INTEGER}},
{PEAK_DB, {TTYP_PEAK_DB, FIELD_DOUBLE}},
{PERCEIVED_DB, {TTYP_PERCEIVED_DB, FIELD_DOUBLE}}, // may be negative
// list
{LABEL, {TTYP_LABEL, FIELD_STRING_LIST}}, // is LIST (not limited string set, despite appearances)
{POS, {TTYP_POS, FIELD_DOUBLE}},
{TYPE, {TTYP_TYPE, FIELD_INTEGER}} // actually limited integer set
};
}
// DTOR