diff options
author | Owen Williams <owilliams@mixxx.org> | 2014-01-10 22:33:44 -0500 |
---|---|---|
committer | Owen Williams <owilliams@mixxx.org> | 2014-01-10 22:33:44 -0500 |
commit | 7c50246ce375161d7f4dcda2bc2cf5a58ebef970 (patch) | |
tree | 5a23c281f5c1165075e66d0a9dba467073c034df /lib | |
parent | bed60ca6d326a397fea175bbd0a75fe85989d7db (diff) |
Update xwax to 1.4, no major changes.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/xwax/debug.h | 8 | ||||
-rw-r--r-- | lib/xwax/lut.c | 2 | ||||
-rw-r--r-- | lib/xwax/lut.cpp | 6 | ||||
-rw-r--r-- | lib/xwax/lut.h | 2 | ||||
-rw-r--r-- | lib/xwax/pitch.h | 2 | ||||
-rw-r--r-- | lib/xwax/timecoder.c | 118 | ||||
-rw-r--r-- | lib/xwax/timecoder.h | 7 | ||||
-rwxr-xr-x | lib/xwax/timecoder_win32.cpp | 125 |
8 files changed, 165 insertions, 105 deletions
diff --git a/lib/xwax/debug.h b/lib/xwax/debug.h index 4b06ba4f73..cc2872b6a7 100644 --- a/lib/xwax/debug.h +++ b/lib/xwax/debug.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,7 +23,11 @@ #include <stdio.h> #ifdef DEBUG -#define debug(...) fprintf(stderr, __VA_ARGS__) +#define debug(...) { \ + fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fputc('\n', stderr); \ +} #define dassert(x) assert(x) #else #define debug(...) diff --git a/lib/xwax/lut.c b/lib/xwax/lut.c index 7ae7733cf7..6f02680e5c 100644 --- a/lib/xwax/lut.c +++ b/lib/xwax/lut.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/lib/xwax/lut.cpp b/lib/xwax/lut.cpp index 30dadfd95e..a10face3f4 100644 --- a/lib/xwax/lut.cpp +++ b/lib/xwax/lut.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -46,13 +46,13 @@ int lut_init(struct lut *lut, int nslots) " (%d slots per hash, %zuKb)\n", hashes, nslots, nslots / hashes, bytes / 1024); - lut->slot = (struct slot*)malloc(sizeof(struct slot) * nslots); + lut->slot = static_cast<struct slot*>(malloc(sizeof(struct slot) * nslots)); if (lut->slot == NULL) { perror("malloc"); return -1; } - lut->table = (slot_no_t*)malloc(sizeof(slot_no_t) * hashes); + lut->table = static_cast<slot_no_t*>(malloc(sizeof(slot_no_t) * hashes)); if (lut->table == NULL) { perror("malloc"); return -1; diff --git a/lib/xwax/lut.h b/lib/xwax/lut.h index a156f492a3..29361c5b98 100644 --- a/lib/xwax/lut.h +++ b/lib/xwax/lut.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/lib/xwax/pitch.h b/lib/xwax/pitch.h index ab0cad5dd8..abf35e3c4d 100644 --- a/lib/xwax/pitch.h +++ b/lib/xwax/pitch.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/lib/xwax/timecoder.c b/lib/xwax/timecoder.c index ec11bbd0de..082af25d87 100644 --- a/lib/xwax/timecoder.c +++ b/lib/xwax/timecoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,6 +18,7 @@ */ #include <assert.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -26,7 +27,7 @@ #include "debug.h" #include "timecoder.h" -#define ZERO_THRESHOLD 128 +#define ZERO_THRESHOLD (128 << 16) #define ZERO_RC 0.001 /* time constant for zero/rumble filter */ @@ -194,7 +195,7 @@ static inline bits_t rev(bits_t current, struct timecode_def *def) static int build_lookup(struct timecode_def *def) { unsigned int n; - bits_t current, last; + bits_t current; if (def->lookup) return 0; @@ -208,12 +209,17 @@ static int build_lookup(struct timecode_def *def) current = def->seed; for (n = 0; n < def->length; n++) { + bits_t next; + /* timecode must not wrap */ dassert(lut_lookup(&def->lut, current) == (unsigned)-1); lut_push(&def->lut, current); - last = current; - current = fwd(current, def); - dassert(rev(current, def) == last); + + /* check symmetry of the lfsr functions */ + next = fwd(current, def); + dassert(rev(next, def) == current); + + current = next; } def->lookup = true; @@ -284,7 +290,7 @@ static void init_channel(struct timecoder_channel *ch) */ void timecoder_init(struct timecoder *tc, struct timecode_def *def, - double speed, unsigned int sample_rate) + double speed, unsigned int sample_rate, bool phono) { assert(def != NULL); @@ -297,13 +303,16 @@ void timecoder_init(struct timecoder *tc, struct timecode_def *def, tc->dt = 1.0 / sample_rate; tc->zero_alpha = tc->dt / (ZERO_RC + tc->dt); + tc->threshold = ZERO_THRESHOLD; + if (phono) + tc->threshold >>= 5; /* approx -36dB */ tc->forwards = 1; init_channel(&tc->primary); init_channel(&tc->secondary); pitch_init(&tc->pitch, tc->dt); - tc->ref_level = 32768.0; + tc->ref_level = INT_MAX; tc->bitstream = 0; tc->timecode = 0; tc->valid_counter = 0; @@ -360,16 +369,17 @@ void timecoder_monitor_clear(struct timecoder *tc) */ static void detect_zero_crossing(struct timecoder_channel *ch, - signed int v, double alpha) + signed int v, double alpha, + signed int threshold) { ch->crossing_ticker++; ch->swapped = false; - if (v > ch->zero + ZERO_THRESHOLD && !ch->positive) { + if (v > ch->zero + threshold && !ch->positive) { ch->swapped = true; ch->positive = true; ch->crossing_ticker = 0; - } else if (v < ch->zero - ZERO_THRESHOLD && ch->positive) { + } else if (v < ch->zero - threshold && ch->positive) { ch->swapped = true; ch->positive = false; ch->crossing_ticker = 0; @@ -384,31 +394,35 @@ static void detect_zero_crossing(struct timecoder_channel *ch, static void update_monitor(struct timecoder *tc, signed int x, signed int y) { - int px, py, p; - double v, w; + int px, py, size, ref; if (!tc->mon) return; + size = tc->mon_size; + ref = tc->ref_level; + /* Decay the pixels already in the montior */ if (++tc->mon_counter % MONITOR_DECAY_EVERY == 0) { - for (p = 0; p < SQ(tc->mon_size); p++) { + int p; + + for (p = 0; p < SQ(size); p++) { if (tc->mon[p]) tc->mon[p] = tc->mon[p] * 7 / 8; } } - v = (double)x / tc->ref_level / 2; - w = (double)y / tc->ref_level / 2; + assert(ref > 0); - px = tc->mon_size / 2 + (v * tc->mon_size / 2); - py = tc->mon_size / 2 + (w * tc->mon_size / 2); + /* ref_level is half the prevision of signal level */ + px = size / 2 + (long long)x * size / ref / 8; + py = size / 2 + (long long)y * size / ref / 8; - /* Set the pixel value to white */ + if (px < 0 || px >= size || py < 0 || py >= size) + return; - if (px > 0 && px < tc->mon_size && py > 0 && py < tc->mon_size) - tc->mon[py * tc->mon_size + px] = 0xff; + tc->mon[py * size + px] = 0xff; /* white */ } /* @@ -453,9 +467,10 @@ static void process_bitstream(struct timecoder *tc, signed int m) /* Adjust the reference level based on this new peak */ - tc->ref_level = (tc->ref_level * (REF_PEAKS_AVG - 1) + m) / REF_PEAKS_AVG; + tc->ref_level -= tc->ref_level / REF_PEAKS_AVG; + tc->ref_level += m / REF_PEAKS_AVG; - debug("%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)\n", + debug("%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)", tc->primary.zero, m, tc->ref_level, b, tc->valid_counter == 0 ? 'x' : ' ', @@ -464,17 +479,16 @@ static void process_bitstream(struct timecoder *tc, signed int m) /* * Process a single sample from the incoming audio + * + * The two input signals (primary and secondary) are in the full range + * of a signed int; ie. 32-bit signed. */ static void process_sample(struct timecoder *tc, signed int primary, signed int secondary) { - signed int m; /* pcm sample, sum of two shorts */ - - detect_zero_crossing(&tc->primary, primary, tc->zero_alpha); - detect_zero_crossing(&tc->secondary, secondary, tc->zero_alpha); - - m = abs(primary - tc->primary.zero); + detect_zero_crossing(&tc->primary, primary, tc->zero_alpha, tc->threshold); + detect_zero_crossing(&tc->secondary, secondary, tc->zero_alpha, tc->threshold); /* If an axis has been crossed, use the direction of the crossing * to work out the direction of the vinyl */ @@ -517,6 +531,10 @@ static void process_sample(struct timecoder *tc, if (tc->secondary.swapped && tc->primary.positive == ((tc->def->flags & SWITCH_POLARITY) == 0)) { + signed int m; + + /* scale to avoid clipping */ + m = abs(primary / 2 - tc->primary.zero / 2); process_bitstream(tc, m); } @@ -557,24 +575,29 @@ void timecoder_cycle_definition(struct timecoder *tc) /* * Submit and decode a block of PCM audio data to the timecode decoder + * + * PCM data is in the full range of signed short; ie. 16-bit signed. */ -void timecoder_submit(struct timecoder *tc, const signed short *pcm, size_t npcm) +void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm) { while (npcm--) { - signed int primary, secondary; + signed int left, right, primary, secondary; + + left = pcm[0] << 16; + right = pcm[1] << 16; if (tc->def->flags & SWITCH_PRIMARY) { - primary = pcm[0]; - secondary = pcm[1]; + primary = left; + secondary = right; } else { - primary = pcm[1]; - secondary = pcm[0]; + primary = right; + secondary = left; } process_sample(tc, primary, secondary); + update_monitor(tc, left, right); - update_monitor(tc, pcm[0], pcm[1]); pcm += TIMECODER_CHANNELS; } } @@ -595,17 +618,20 @@ signed int timecoder_get_position(struct timecoder *tc, double *when) { signed int r; - if (tc->valid_counter > VALID_BITS) { - r = lut_lookup(&tc->def->lut, tc->bitstream); + if (tc->valid_counter <= VALID_BITS) + return -1; + + r = lut_lookup(&tc->def->lut, tc->bitstream); + if (r == -1) + return -1; - if (r >= 0) { - //normalize position to milliseconds, not timecode steps -- Owen - r = (float)r * (1000.0 / (tc->def->resolution * tc->speed)); - if (when) - *when = tc->timecode_ticker * tc->dt; - return r; - } + if (r >= 0) { + // normalize position to milliseconds, not timecode steps -- Owen + r = (double)r * (1000.0 / ((double)tc->def->resolution * tc->speed)); } - return -1; + if (when) + *when = tc->timecode_ticker * tc->dt; + + return r; } diff --git a/lib/xwax/timecoder.h b/lib/xwax/timecoder.h index fda86fff5e..3304eee641 100644 --- a/lib/xwax/timecoder.h +++ b/lib/xwax/timecoder.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -58,6 +58,7 @@ struct timecoder { /* Precomputed values */ double dt, zero_alpha; + signed int threshold; /* Pitch information */ @@ -83,14 +84,14 @@ struct timecode_def* timecoder_find_definition(const char *name); void timecoder_free_lookup(void); void timecoder_init(struct timecoder *tc, struct timecode_def *def, - double speed, unsigned int sample_rate); + double speed, unsigned int sample_rate, bool phono); void timecoder_clear(struct timecoder *tc); int timecoder_monitor_init(struct timecoder *tc, int size); void timecoder_monitor_clear(struct timecoder *tc); void timecoder_cycle_definition(struct timecoder *tc); -void timecoder_submit(struct timecoder *tc, const signed short *pcm, size_t npcm); +void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm); signed int timecoder_get_position(struct timecoder *tc, double *when); /* diff --git a/lib/xwax/timecoder_win32.cpp b/lib/xwax/timecoder_win32.cpp index 2059ebdd53..18910382f5 100755 --- a/lib/xwax/timecoder_win32.cpp +++ b/lib/xwax/timecoder_win32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Mark Hills <mark@pogo.org.uk> + * Copyright (C) 2013 Mark Hills <mark@xwax.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,6 +18,7 @@ */ #include <assert.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -28,7 +29,7 @@ #include "debug.h" #include "timecoder.h" -#define ZERO_THRESHOLD 128 +#define ZERO_THRESHOLD (128 << 16) #define ZERO_RC 0.001 /* time constant for zero/rumble filter */ @@ -98,7 +99,7 @@ static struct timecode_def timecodes[] = { 0x041040, 1500000, 605000, - false + false }, { "traktor_b", @@ -140,6 +141,7 @@ static struct timecode_def timecodes[] = { NULL } }; + /* * Calculate LFSR bit */ @@ -198,7 +200,7 @@ static inline bits_t rev(bits_t current, struct timecode_def *def) static int build_lookup(struct timecode_def *def) { unsigned int n; - bits_t current, last; + bits_t current; if (def->lookup) return 0; @@ -212,12 +214,17 @@ static int build_lookup(struct timecode_def *def) current = def->seed; for (n = 0; n < def->length; n++) { + bits_t next; + /* timecode must not wrap */ dassert(lut_lookup(&def->lut, current) == (unsigned)-1); lut_push(&def->lut, current); - last = current; - current = fwd(current, def); - dassert(rev(current, def) == last); + + /* check symmetry of the lfsr functions */ + next = fwd(current, def); + dassert(rev(next, def) == current); + + current = next; } def->lookup = true; @@ -288,7 +295,7 @@ static void init_channel(struct timecoder_channel *ch) */ void timecoder_init(struct timecoder *tc, struct timecode_def *def, - double speed, unsigned int sample_rate) + double speed, unsigned int sample_rate, bool phono) { assert(def != NULL); @@ -301,13 +308,16 @@ void timecoder_init(struct timecoder *tc, struct timecode_def *def, tc->dt = 1.0 / sample_rate; tc->zero_alpha = tc->dt / (ZERO_RC + tc->dt); + tc->threshold = ZERO_THRESHOLD; + if (phono) + tc->threshold >>= 5; /* approx -36dB */ tc->forwards = 1; init_channel(&tc->primary); init_channel(&tc->secondary); pitch_init(&tc->pitch, tc->dt); - tc->ref_level = 32768.0; + tc->ref_level = INT_MAX; tc->bitstream = 0; tc->timecode = 0; tc->valid_counter = 0; @@ -338,7 +348,7 @@ int timecoder_monitor_init(struct timecoder *tc, int size) { assert(tc->mon == NULL); tc->mon_size = size; - tc->mon = (unsigned char*)malloc(SQ(tc->mon_size)); + tc->mon = static_cast<unsigned char*>(malloc(SQ(tc->mon_size))); if (tc->mon == NULL) { perror("malloc"); return -1; @@ -364,16 +374,17 @@ void timecoder_monitor_clear(struct timecoder *tc) */ static void detect_zero_crossing(struct timecoder_channel *ch, - signed int v, double alpha) + signed int v, double alpha, + signed int threshold) { ch->crossing_ticker++; ch->swapped = false; - if (v > ch->zero + ZERO_THRESHOLD && !ch->positive) { + if (v > ch->zero + threshold && !ch->positive) { ch->swapped = true; ch->positive = true; ch->crossing_ticker = 0; - } else if (v < ch->zero - ZERO_THRESHOLD && ch->positive) { + } else if (v < ch->zero - threshold && ch->positive) { ch->swapped = true; ch->positive = false; ch->crossing_ticker = 0; @@ -388,31 +399,35 @@ static void detect_zero_crossing(struct timecoder_channel *ch, static void update_monitor(struct timecoder *tc, signed int x, signed int y) { - int px, py, p; - double v, w; + int px, py, size, ref; if (!tc->mon) return; + size = tc->mon_size; + ref = tc->ref_level; + /* Decay the pixels already in the montior */ if (++tc->mon_counter % MONITOR_DECAY_EVERY == 0) { - for (p = 0; p < SQ(tc->mon_size); p++) { + int p; + + for (p = 0; p < SQ(size); p++) { if (tc->mon[p]) tc->mon[p] = tc->mon[p] * 7 / 8; } } - v = (double)x / tc->ref_level / 2; - w = (double)y / tc->ref_level / 2; + assert(ref > 0); - px = tc->mon_size / 2 + (v * tc->mon_size / 2); - py = tc->mon_size / 2 + (w * tc->mon_size / 2); + /* ref_level is half the prevision of signal level */ + px = size / 2 + (long long)x * size / ref / 8; + py = size / 2 + (long long)y * size / ref / 8; - /* Set the pixel value to white */ + if (px < 0 || px >= size || py < 0 || py >= size) + return; - if (px > 0 && px < tc->mon_size && py > 0 && py < tc->mon_size) - tc->mon[py * tc->mon_size + px] = 0xff; + tc->mon[py * size + px] = 0xff; /* white */ } /* @@ -457,9 +472,10 @@ static void process_bitstream(struct timecoder *tc, signed int m) /* Adjust the reference level based on this new peak */ - tc->ref_level = (tc->ref_level * (REF_PEAKS_AVG - 1) + m) / REF_PEAKS_AVG; + tc->ref_level -= tc->ref_level / REF_PEAKS_AVG; + tc->ref_level += m / REF_PEAKS_AVG; - debug("%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)\n", + debug("%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)", tc->primary.zero, m, tc->ref_level, b, tc->valid_counter == 0 ? 'x' : ' ', @@ -468,17 +484,16 @@ static void process_bitstream(struct timecoder *tc, signed int m) /* * Process a single sample from the incoming audio + * + * The two input signals (primary and secondary) are in the full range + * of a signed int; ie. 32-bit signed. */ static void process_sample(struct timecoder *tc, signed int primary, signed int secondary) { - signed int m; /* pcm sample, sum of two shorts */ - - detect_zero_crossing(&tc->primary, primary, tc->zero_alpha); - detect_zero_crossing(&tc->secondary, secondary, tc->zero_alpha); - - m = abs(primary - tc->primary.zero); + detect_zero_crossing(&tc->primary, primary, tc->zero_alpha, tc->threshold); + detect_zero_crossing(&tc->secondary, secondary, tc->zero_alpha, tc->threshold); /* If an axis has been crossed, use the direction of the crossing * to work out the direction of the vinyl */ @@ -521,6 +536,10 @@ static void process_sample(struct timecoder *tc, if (tc->secondary.swapped && tc->primary.positive == ((tc->def->flags & SWITCH_POLARITY) == 0)) { + signed int m; + + /* scale to avoid clipping */ + m = abs(primary / 2 - tc->primary.zero / 2); process_bitstream(tc, m); } @@ -561,24 +580,29 @@ void timecoder_cycle_definition(struct timecoder *tc) /* * Submit and decode a block of PCM audio data to the timecode decoder + * + * PCM data is in the full range of signed short; ie. 16-bit signed. */ -void timecoder_submit(struct timecoder *tc, const signed short *pcm, size_t npcm) +void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm) { while (npcm--) { - signed int primary, secondary; + signed int left, right, primary, secondary; + + left = pcm[0] << 16; + right = pcm[1] << 16; if (tc->def->flags & SWITCH_PRIMARY) { - primary = pcm[0]; - secondary = pcm[1]; + primary = left; + secondary = right; } else { - primary = pcm[1]; - secondary = pcm[0]; + primary = right; + secondary = left; } process_sample(tc, primary, secondary); + update_monitor(tc, left, right); - update_monitor(tc, pcm[0], pcm[1]); pcm += TIMECODER_CHANNELS; } } @@ -599,17 +623,22 @@ signed int timecoder_get_position(struct timecoder *tc, double *when) { signed int r; - if (tc->valid_counter > VALID_BITS) { - r = lut_lookup(&tc->def->lut, tc->bitstream); + if (tc->valid_counter <= VALID_BITS) + return -1; - if (r >= 0) { - //normalize position to milliseconds, not timecode steps -- Owen - r = (float)r * (1000.0 / (tc->def->resolution * tc->speed)); - if (when) - *when = tc->timecode_ticker * tc->dt; - return r; - } + r = lut_lookup(&tc->def->lut, tc->bitstream); + if (r == -1) + return -1; + + if (r >= 0) { + // normalize position to milliseconds, not timecode steps -- Owen + r = static_cast<double>(r) + * (1000.0 + / (static_cast<double>(tc->def->resolution) * tc->speed)); } - return -1; + if (when) + *when = tc->timecode_ticker * tc->dt; + + return r; } |