From 98750593daa4139de4b0f063b0eadb957e17f2f7 Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sun, 4 Nov 2012 21:13:10 -0500 Subject: [PATCH 1/7] Updates to Fix Bad_Access from timecoder_submit() must multiply buffersize by nChannels --- src/ofxXwax.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ofxXwax.cpp b/src/ofxXwax.cpp index 8d5e079..358f8d5 100644 --- a/src/ofxXwax.cpp +++ b/src/ofxXwax.cpp @@ -33,7 +33,7 @@ void ofxXwax::update(float* input) { shortBuffer[i] = input[i] * (1<<15); } - timecoder_submit(&timecoder, &shortBuffer[0], bufferSize); + timecoder_submit(&timecoder, &shortBuffer[0], bufferSize*nChannels); float when; float curPosition = timecoder_get_position(&timecoder, &when); @@ -77,4 +77,4 @@ bool ofxXwax::isAbsoluteValid() const { float ofxXwax::millisToDegrees(float millis) { return (millis / msPerRotation) * 360; -} \ No newline at end of file +} From b7c4e3f9372f12f62436772c1bf303e5192298af Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sun, 4 Nov 2012 23:26:38 -0500 Subject: [PATCH 2/7] Updates to include new Xwax libs WIP --- libs/xwax/lut.c | 21 +-- libs/xwax/lut.cpp | 110 ------------- libs/xwax/lut.h | 16 +- libs/xwax/pitch.h | 16 +- libs/xwax/timecoder.c | 357 ++++++++++++++++++++++++++---------------- libs/xwax/timecoder.h | 94 +++++------ src/ofxXwax.cpp | 12 +- src/ofxXwax.h | 2 +- 8 files changed, 308 insertions(+), 320 deletions(-) delete mode 100644 libs/xwax/lut.cpp diff --git a/libs/xwax/lut.c b/libs/xwax/lut.c index a914272..7ae7733 100644 --- a/libs/xwax/lut.c +++ b/libs/xwax/lut.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,25 +34,25 @@ /* Initialise an empty hash lookup table to store the given number * of timecode -> position lookups */ -int lut_init(struct lut_t *lut, int nslots) +int lut_init(struct lut *lut, int nslots) { int n, hashes; size_t bytes; hashes = 1 << HASH_BITS; - bytes = sizeof(struct slot_t) * nslots + sizeof(slot_no_t) * hashes; + bytes = sizeof(struct slot) * nslots + sizeof(slot_no_t) * hashes; fprintf(stderr, "Lookup table has %d hashes to %d slots" " (%d slots per hash, %zuKb)\n", hashes, nslots, nslots / hashes, bytes / 1024); - lut->slot = (struct slot_t*)malloc(sizeof(struct slot_t) * nslots); + lut->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 = malloc(sizeof(slot_no_t) * hashes); if (lut->table == NULL) { perror("malloc"); return -1; @@ -67,17 +67,18 @@ int lut_init(struct lut_t *lut, int nslots) } -void lut_clear(struct lut_t *lut) +void lut_clear(struct lut *lut) { free(lut->table); + free(lut->slot); } -void lut_push(struct lut_t *lut, unsigned int timecode) +void lut_push(struct lut *lut, unsigned int timecode) { unsigned int hash; slot_no_t slot_no; - struct slot_t *slot; + struct slot *slot; slot_no = lut->avail++; /* take the next available slot */ @@ -90,11 +91,11 @@ void lut_push(struct lut_t *lut, unsigned int timecode) } -unsigned int lut_lookup(struct lut_t *lut, unsigned int timecode) +unsigned int lut_lookup(struct lut *lut, unsigned int timecode) { unsigned int hash; slot_no_t slot_no; - struct slot_t *slot; + struct slot *slot; hash = HASH(timecode); slot_no = lut->table[hash]; diff --git a/libs/xwax/lut.cpp b/libs/xwax/lut.cpp deleted file mode 100644 index a914272..0000000 --- a/libs/xwax/lut.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2010 Mark Hills - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -#include -#include - -#include "lut.h" - -/* The number of bits to form the hash, which governs the overall size - * of the hash lookup table, and hence the amount of chaining */ - -#define HASH_BITS 16 - -#define HASH(timecode) ((timecode) & ((1 << HASH_BITS) - 1)) -#define NO_SLOT ((unsigned)-1) - - -/* Initialise an empty hash lookup table to store the given number - * of timecode -> position lookups */ - -int lut_init(struct lut_t *lut, int nslots) -{ - int n, hashes; - size_t bytes; - - hashes = 1 << HASH_BITS; - bytes = sizeof(struct slot_t) * nslots + sizeof(slot_no_t) * hashes; - - fprintf(stderr, "Lookup table has %d hashes to %d slots" - " (%d slots per hash, %zuKb)\n", - hashes, nslots, nslots / hashes, bytes / 1024); - - lut->slot = (struct slot_t*)malloc(sizeof(struct slot_t) * nslots); - if (lut->slot == NULL) { - perror("malloc"); - return -1; - } - - lut->table = (slot_no_t*)malloc(sizeof(slot_no_t) * hashes); - if (lut->table == NULL) { - perror("malloc"); - return -1; - } - - for (n = 0; n < hashes; n++) - lut->table[n] = NO_SLOT; - - lut->avail = 0; - - return 0; -} - - -void lut_clear(struct lut_t *lut) -{ - free(lut->table); -} - - -void lut_push(struct lut_t *lut, unsigned int timecode) -{ - unsigned int hash; - slot_no_t slot_no; - struct slot_t *slot; - - slot_no = lut->avail++; /* take the next available slot */ - - slot = &lut->slot[slot_no]; - slot->timecode = timecode; - - hash = HASH(timecode); - slot->next = lut->table[hash]; - lut->table[hash] = slot_no; -} - - -unsigned int lut_lookup(struct lut_t *lut, unsigned int timecode) -{ - unsigned int hash; - slot_no_t slot_no; - struct slot_t *slot; - - hash = HASH(timecode); - slot_no = lut->table[hash]; - - while (slot_no != NO_SLOT) { - slot = &lut->slot[slot_no]; - if (slot->timecode == timecode) - return slot_no; - slot_no = slot->next; - } - - return (unsigned)-1; -} diff --git a/libs/xwax/lut.h b/libs/xwax/lut.h index 46c4bd3..a156f49 100644 --- a/libs/xwax/lut.h +++ b/libs/xwax/lut.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,21 +22,21 @@ typedef unsigned int slot_no_t; -struct slot_t { +struct slot { unsigned int timecode; slot_no_t next; /* next slot with the same hash */ }; -struct lut_t { - struct slot_t *slot; +struct lut { + struct slot *slot; slot_no_t *table, /* hash -> slot lookup */ avail; /* next available slot */ }; -int lut_init(struct lut_t *lut, int nslots); -void lut_clear(struct lut_t *lut); +int lut_init(struct lut *lut, int nslots); +void lut_clear(struct lut *lut); -void lut_push(struct lut_t *lut, unsigned int timecode); -unsigned int lut_lookup(struct lut_t *lut, unsigned int timecode); +void lut_push(struct lut *lut, unsigned int timecode); +unsigned int lut_lookup(struct lut *lut, unsigned int timecode); #endif diff --git a/libs/xwax/pitch.h b/libs/xwax/pitch.h index 076af71..ab0cad5 100644 --- a/libs/xwax/pitch.h +++ b/libs/xwax/pitch.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,17 +23,17 @@ /* Values for the filter concluded experimentally */ #define ALPHA (1.0/512) -#define BETA (ALPHA/1024) +#define BETA (ALPHA/256) /* State of the pitch calculation filter */ -struct pitch_t { - float dt, x, v; +struct pitch { + double dt, x, v; }; /* Prepare the filter for observations every dt seconds */ -static inline void pitch_init(struct pitch_t *p, float dt) +static inline void pitch_init(struct pitch *p, double dt) { p->dt = dt; p->x = 0.0; @@ -46,9 +46,9 @@ static inline void pitch_init(struct pitch_t *p, float dt) * Because the vinyl uses timestamps, the values for dx are discrete * rather than smooth. */ -static inline void pitch_dt_observation(struct pitch_t *p, float dx) +static inline void pitch_dt_observation(struct pitch *p, double dx) { - float predicted_x, predicted_v, residual_x; + double predicted_x, predicted_v, residual_x; predicted_x = p->x + p->v * p->dt; predicted_v = p->v; @@ -63,7 +63,7 @@ static inline void pitch_dt_observation(struct pitch_t *p, float dx) /* Get the pitch after filtering */ -static inline float pitch_current(struct pitch_t *p) +static inline double pitch_current(struct pitch *p) { return p->v; } diff --git a/libs/xwax/timecoder.c b/libs/xwax/timecoder.c index 2bf0f2a..ffa010e 100644 --- a/libs/xwax/timecoder.c +++ b/libs/xwax/timecoder.c @@ -1,15 +1,15 @@ /* - * Copyright (C) 2010 Mark Hills + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2, as published by the Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details. - * + * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, @@ -31,16 +31,16 @@ #define REF_PEAKS_AVG 48 /* in wave cycles */ -/* The number of correct bits which come in before the timecode - * is declared valid. Set this too low, and risk the record skipping around - * (often to blank areas of track) during scratching */ +/* The number of correct bits which come in before the timecode is + * declared valid. Set this too low, and risk the record skipping + * around (often to blank areas of track) during scratching */ #define VALID_BITS 24 #define MONITOR_DECAY_EVERY 512 /* in samples */ #define SQ(x) ((x)*(x)) - +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) /* Timecode definitions */ @@ -48,8 +48,7 @@ #define SWITCH_PRIMARY 0x2 /* use left channel (not right) as primary */ #define SWITCH_POLARITY 0x4 /* read bit values in negative (not positive) */ - -static struct timecode_def_t timecode_def[] = { +static struct timecode_def timecodes[] = { { .name = "serato_2a", .desc = "Serato 2nd Ed., side A", @@ -59,7 +58,7 @@ static struct timecode_def_t timecode_def[] = { .seed = 0x59017, .taps = 0x361e4, .length = 712000, - .safe = 625000, + .safe = 707000, .lookup = false }, { @@ -71,7 +70,7 @@ static struct timecode_def_t timecode_def[] = { .seed = 0x8f3c6, .taps = 0x4f0d8, /* reverse of side A */ .length = 922000, - .safe = 905000, + .safe = 917000, .lookup = false }, { @@ -83,7 +82,7 @@ static struct timecode_def_t timecode_def[] = { .seed = 0xd8b40, .taps = 0x34d54, .length = 950000, - .safe = 890000, + .safe = 940000, .lookup = false }, { @@ -95,8 +94,8 @@ static struct timecode_def_t timecode_def[] = { .seed = 0x134503, .taps = 0x041040, .length = 1500000, - .safe = 1214000, - .lookup = false + .safe = 1480000, + .lookup = false }, { .name = "traktor_b", @@ -107,7 +106,7 @@ static struct timecode_def_t timecode_def[] = { .seed = 0x32066c, .taps = 0x041040, /* same as side A */ .length = 2110000, - .safe = 1814000, + .safe = 2090000, .lookup = false }, { @@ -134,14 +133,11 @@ static struct timecode_def_t timecode_def[] = { .safe = 310000, .lookup = false }, - { - .name = NULL - } }; - -/* Linear Feeback Shift Register in the forward direction. New values - * are generated at the least-significant bit. */ +/* + * Calculate LFSR bit + */ static inline bits_t lfsr(bits_t code, bits_t taps) { @@ -158,8 +154,12 @@ static inline bits_t lfsr(bits_t code, bits_t taps) return xrs & 0x1; } +/* + * Linear Feedback Shift Register in the forward direction. New values + * are generated at the least-significant bit. + */ -static inline bits_t fwd(bits_t current, struct timecode_def_t *def) +static inline bits_t fwd(bits_t current, struct timecode_def *def) { bits_t l; @@ -169,8 +169,11 @@ static inline bits_t fwd(bits_t current, struct timecode_def_t *def) return (current >> 1) | (l << (def->bits - 1)); } +/* + * Linear Feedback Shift Register in the reverse direction + */ -static inline bits_t rev(bits_t current, struct timecode_def_t *def) +static inline bits_t rev(bits_t current, struct timecode_def *def) { bits_t l, mask; @@ -181,24 +184,13 @@ static inline bits_t rev(bits_t current, struct timecode_def_t *def) return ((current << 1) & mask) | l; } +/* + * Where necessary, build the lookup table required for this timecode + * + * Return: -1 if not enough memory could be allocated, otherwise 0 + */ -static struct timecode_def_t* find_definition(const char *name) -{ - struct timecode_def_t *def; - - def = &timecode_def[0]; - while (def->name) { - if (!strcmp(def->name, name)) - return def; - def++; - } - return NULL; -} - - -/* Where necessary, build the lookup table required for this timecode */ - -static int build_lookup(struct timecode_def_t *def) +static int build_lookup(struct timecode_def *def) { unsigned int n; bits_t current, last; @@ -213,58 +205,97 @@ static int build_lookup(struct timecode_def_t *def) return -1; current = def->seed; - + for (n = 0; n < def->length; n++) { /* timecode must not wrap */ - assert(lut_lookup(&def->lut, current) == (unsigned)-1); + if(lut_lookup(&def->lut, current) == (unsigned)-1){ + lut_push(&def->lut, current); last = current; current = fwd(current, def); - assert(rev(current, def) == last); + if(rev(current, def) == last){ + + } + } } def->lookup = true; - - return 0; + + return 0; } +/* + * Find a timecode definition by name + * + * Return: pointer to timecode definition, or NULL if not found + */ + +struct timecode_def* timecoder_find_definition(const char *name) +{ + struct timecode_def *def, *end; -/* Free the timecoder lookup tables when they are no longer needed */ + def = &timecodes[0]; + end = def + ARRAY_SIZE(timecodes); + + for (;;) { + if (!strcmp(def->name, name)) + break; + + def++; + + if (def == end) + return NULL; + } + + if (build_lookup(def) == -1) + return NULL; + + return def; +} + +/* + * Free the timecoder lookup tables when they are no longer needed + */ void timecoder_free_lookup(void) { - struct timecode_def_t *def; + struct timecode_def *def, *end; - def = &timecode_def[0]; - while (def->name) { + def = &timecodes[0]; + end = def + ARRAY_SIZE(timecodes); + + while (def < end) { if (def->lookup) lut_clear(&def->lut); def++; } } +/* + * Initialise filter values for one channel + */ -static void init_channel(struct timecoder_channel_t *ch) +static void init_channel(struct timecoder_channel *ch) { - ch->positive = 0; + ch->positive = false; ch->zero = 0; } +/* + * Initialise a timecode decoder at the given reference speed + * + * Return: -1 if the timecoder could not be initialised, otherwise 0 + */ -/* Initialise a timecode decoder at the given reference speed */ - -int timecoder_init(struct timecoder_t *tc, const char *def_name, double speed, - unsigned int sample_rate) +void timecoder_init(struct timecoder *tc, struct timecode_def *def, + double speed, unsigned int sample_rate) { + if(def != NULL){ + /* A definition contains a lookup table which can be shared * across multiple timecoders */ - tc->def = find_definition(def_name); - if (tc->def == NULL) { - fprintf(stderr, "Timecode definition '%s' is not known.\n", def_name); - return -1; - } - if (build_lookup(tc->def) == -1) - return -1; + if(def->lookup){ + tc->def = def; tc->speed = speed; tc->dt = 1.0 / sample_rate; @@ -282,25 +313,33 @@ int timecoder_init(struct timecoder_t *tc, const char *def_name, double speed, tc->timecode_ticker = 0; tc->mon = NULL; - - return 0; + } + } } +/* + * Clear resources associated with a timecode decoder + */ -/* Clear a timecode decoder */ - -void timecoder_clear(struct timecoder_t *tc) +void timecoder_clear(struct timecoder *tc) { - timecoder_monitor_clear(tc); + if(tc->mon == NULL){ + + } } +/* + * Initialise a raster display of the incoming audio + * + * The monitor (otherwise known as 'scope' in the interface) is an x-y + * display of the post-calibrated incoming audio. + * + * Return: -1 if not enough memory could be allocated, otherwise 0 + */ -/* The monitor (otherwise known as 'scope' in the interface) is the - * display of the incoming audio. Initialise one for the given - * timecoder */ - -int timecoder_monitor_init(struct timecoder_t *tc, int size) +int timecoder_monitor_init(struct timecoder *tc, int size) { + if(tc->mon == NULL){ tc->mon_size = size; tc->mon = malloc(SQ(tc->mon_size)); if (tc->mon == NULL) { @@ -309,76 +348,84 @@ int timecoder_monitor_init(struct timecoder_t *tc, int size) } memset(tc->mon, 0, SQ(tc->mon_size)); tc->mon_counter = 0; + } return 0; } +/* + * Clear the monitor on the given timecoder + */ -/* Clear the monitor on the given timecoder */ - -void timecoder_monitor_clear(struct timecoder_t *tc) +void timecoder_monitor_clear(struct timecoder *tc) { - if (tc->mon) { - free(tc->mon); - tc->mon = NULL; + if(tc->mon != NULL){ + free(tc->mon); + tc->mon = NULL; } } +/* + * Update channel information with axis-crossings + */ -static void detect_zero_crossing(struct timecoder_channel_t *ch, - signed int v, float alpha) +static void detect_zero_crossing(struct timecoder_channel *ch, + signed int v, double alpha) { ch->crossing_ticker++; - ch->swapped = 0; + ch->swapped = false; if (v > ch->zero + ZERO_THRESHOLD && !ch->positive) { - ch->swapped = 1; - ch->positive = 1; + ch->swapped = true; + ch->positive = true; ch->crossing_ticker = 0; } else if (v < ch->zero - ZERO_THRESHOLD && ch->positive) { - ch->swapped = 1; - ch->positive = 0; + ch->swapped = true; + ch->positive = false; ch->crossing_ticker = 0; } - + ch->zero += alpha * (v - ch->zero); } +/* + * Plot the given sample value in the x-y monitor + */ -/* Plot the given sample value in the monitor (scope) */ - -static void update_monitor(struct timecoder_t *tc, signed int x, signed int y) +static void update_monitor(struct timecoder *tc, signed int x, signed int y) { int px, py, p; - float v, w; + double v, w; if (!tc->mon) return; /* Decay the pixels already in the montior */ - + if (++tc->mon_counter % MONITOR_DECAY_EVERY == 0) { for (p = 0; p < SQ(tc->mon_size); p++) { - if (tc->mon[p]) + if (tc->mon[p]){ tc->mon[p] = tc->mon[p] * 7 / 8; + } } } - - v = (float)x / tc->ref_level / 2; - w = (float)y / tc->ref_level / 2; - + + v = (double)x / tc->ref_level / 2; + w = (double)y / tc->ref_level / 2; + px = tc->mon_size / 2 + (v * tc->mon_size / 2); py = tc->mon_size / 2 + (w * tc->mon_size / 2); /* Set the pixel value to white */ - + if (px > 0 && px < tc->mon_size && py > 0 && py < tc->mon_size) tc->mon[py * tc->mon_size + px] = 0xff; } +/* + * Extract the bitstream from the sample value + */ -/* Process a single bitstream reading */ - -static void process_bitstream(struct timecoder_t *tc, signed int m) +static void process_bitstream(struct timecoder *tc, signed int m) { bits_t b; @@ -411,28 +458,21 @@ static void process_bitstream(struct timecoder_t *tc, signed int m) } /* Take note of the last time we read a valid timecode */ - + tc->timecode_ticker = 0; /* Adjust the reference level based on this new peak */ tc->ref_level = (tc->ref_level * (REF_PEAKS_AVG - 1) + m) / REF_PEAKS_AVG; -#ifdef DEBUG_BITSTREAM - fprintf(stderr, "%+6d zero, %+6d (ref %+6d)\t= %d%c (%5d)\n", - tc->primary.zero, - m, - tc->ref_level, - b, - tc->valid_counter == 0 ? 'x' : ' ', - tc->valid_counter); -#endif -} +} -/* Process a single sample from the incoming audio */ +/* + * Process a single sample from the incoming audio + */ -static void process_sample(struct timecoder_t *tc, +static void process_sample(struct timecoder *tc, signed int primary, signed int secondary) { signed int m; /* pcm sample, sum of two shorts */ @@ -445,14 +485,22 @@ static void process_sample(struct timecoder_t *tc, /* If an axis has been crossed, use the direction of the crossing * to work out the direction of the vinyl */ - if (tc->primary.swapped) { - tc->forwards = (tc->primary.positive != tc->secondary.positive); - if (tc->def->flags & SWITCH_PHASE) - tc->forwards = !tc->forwards; - } if (tc->secondary.swapped) { - tc->forwards = (tc->primary.positive == tc->secondary.positive); - if (tc->def->flags & SWITCH_PHASE) - tc->forwards = !tc->forwards; + if (tc->primary.swapped || tc->secondary.swapped) { + bool forwards; + + if (tc->primary.swapped) { + forwards = (tc->primary.positive != tc->secondary.positive); + } else { + forwards = (tc->primary.positive == tc->secondary.positive); + } + + if (tc->def->flags & SWITCH_PHASE) + forwards = !forwards; + + if (forwards != tc->forwards) { /* direction has changed */ + tc->forwards = forwards; + tc->valid_counter = 0; + } } /* If any axis has been crossed, register movement using the pitch @@ -461,7 +509,7 @@ static void process_sample(struct timecoder_t *tc, if (!tc->primary.swapped && !tc->secondary.swapped) pitch_dt_observation(&tc->pitch, 0.0); else { - float dx; + double dx; dx = 1.0 / tc->def->resolution / 4; if (!tc->forwards) @@ -481,10 +529,45 @@ static void process_sample(struct timecoder_t *tc, tc->timecode_ticker++; } +/* + * Cycle to the next timecode definition which has a valid lookup + * + * Return: pointer to timecode definition + */ + +static struct timecode_def* next_definition(struct timecode_def *def) +{ + if(def != NULL){ + + do { + def++; + + if (def > timecodes + ARRAY_SIZE(timecodes)) + def = timecodes; + + } while (!def->lookup); + + } + + return def; +} + +/* + * Change the timecode definition to the next available + */ -/* Submit and decode a block of PCM audio data to the timecoder */ +void timecoder_cycle_definition(struct timecoder *tc) +{ + tc->def = next_definition(tc->def); + tc->valid_counter = 0; + tc->timecode_ticker = 0; +} -void timecoder_submit(struct timecoder_t *tc, const signed short *pcm, size_t npcm) +/* + * Submit and decode a block of PCM audio data to the timecode decoder + */ + +void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm) { while (npcm--) { signed int primary, secondary; @@ -499,18 +582,24 @@ void timecoder_submit(struct timecoder_t *tc, const signed short *pcm, size_t np process_sample(tc, primary, secondary); - update_monitor(tc, pcm[0], pcm[1]); + //update_monitor(tc, pcm[0], pcm[1]); pcm += TIMECODER_CHANNELS; } } +/* + * Get the last-known position of the timecode + * + * If now data is available or if too few bits have been error + * checked, then this counts as invalid. The last known position is + * given along with the time elapsed since the position stamp was + * read. + * + * Return: the known position of the timecode, or -1 if not known + * Post: if when != NULL, *when is the elapsed time in seconds + */ -/* Return the known position in the timecode, or -1 if not known. If - * two few bits have been error-checked, then this also counts as - * invalid. If 'when' is given, return the time, in seconds since this - * value was read. */ - -signed int timecoder_get_position(struct timecoder_t *tc, float *when) +signed int timecoder_get_position(struct timecoder *tc, double *when) { signed int r; @@ -518,13 +607,11 @@ signed int timecoder_get_position(struct timecoder_t *tc, float *when) r = lut_lookup(&tc->def->lut, tc->bitstream); 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; } } - + return -1; } diff --git a/libs/xwax/timecoder.h b/libs/xwax/timecoder.h index ccc475c..0002789 100644 --- a/libs/xwax/timecoder.h +++ b/libs/xwax/timecoder.h @@ -1,15 +1,15 @@ -/* - * Copyright (C) 2010 Mark Hills +/* + * Copyright (C) 2012 Mark Hills * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2, as published by the Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details. - * + * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, @@ -20,21 +20,16 @@ #ifndef TIMECODER_H #define TIMECODER_H -#ifndef _MSC_VER #include -#endif -/* #include "device.h" */ #include "lut.h" #include "pitch.h" #define TIMECODER_CHANNELS 2 - typedef unsigned int bits_t; - -struct timecode_def_t { +struct timecode_def { char *name, *desc; int bits, /* number of bits in string */ resolution, /* wave cycles per second */ @@ -44,31 +39,29 @@ struct timecode_def_t { unsigned int length, /* in cycles */ safe; /* last 'safe' timecode number (for auto disconnect) */ bool lookup; /* true if lut has been generated */ - struct lut_t lut; + struct lut lut; }; - -struct timecoder_channel_t { - int positive, /* wave is in positive part of cycle */ +struct timecoder_channel { + bool positive, /* wave is in positive part of cycle */ swapped; /* wave recently swapped polarity */ signed int zero; unsigned int crossing_ticker; /* samples since we last crossed zero */ }; - -struct timecoder_t { - struct timecode_def_t *def; +struct timecoder { + struct timecode_def *def; double speed; /* Precomputed values */ - float dt, zero_alpha; + double dt, zero_alpha; /* Pitch information */ - int forwards; - struct timecoder_channel_t primary, secondary; - struct pitch_t pitch; + bool forwards; + struct timecoder_channel primary, secondary; + struct pitch pitch; /* Numerical timecode */ @@ -84,52 +77,65 @@ struct timecoder_t { int mon_size, mon_counter; }; - +struct timecode_def* timecoder_find_definition(const char *name); void timecoder_free_lookup(void); -int timecoder_init(struct timecoder_t *tc, const char *def_name, double speed, - unsigned int sample_rate); -void timecoder_clear(struct timecoder_t *tc); +void timecoder_init(struct timecoder *tc, struct timecode_def *def, + double speed, unsigned int sample_rate); +void timecoder_clear(struct timecoder *tc); -int timecoder_monitor_init(struct timecoder_t *tc, int size); -void timecoder_monitor_clear(struct timecoder_t *tc); +int timecoder_monitor_init(struct timecoder *tc, int size); +void timecoder_monitor_clear(struct timecoder *tc); -void timecoder_submit(struct timecoder_t *tc, const signed short *pcm, size_t npcm); +void timecoder_cycle_definition(struct timecoder *tc); +void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm); +signed int timecoder_get_position(struct timecoder *tc, double *when); -signed int timecoder_get_position(struct timecoder_t *tc, float *when); +/* + * The timecode definition currently in use by this decoder + */ +static inline struct timecode_def* timecoder_get_definition(struct timecoder *tc) +{ + return tc->def; +} -/* Return the pitch relative to reference playback speed */ +/* + * Return the pitch relative to reference playback speed + */ -static inline float timecoder_get_pitch(struct timecoder_t *tc) +static inline double timecoder_get_pitch(struct timecoder *tc) { return pitch_current(&tc->pitch) / tc->speed; } - -/* The last 'safe' timecode value on the record. Beyond this value, we +/* + * The last 'safe' timecode value on the record. Beyond this value, we * probably want to ignore the timecode values, as we will hit the - * label of the record. */ + * label of the record. + */ -static inline unsigned int timecoder_get_safe(struct timecoder_t *tc) +static inline unsigned int timecoder_get_safe(struct timecoder *tc) { - return tc->def->safe * 1000 / (tc->def->resolution * tc->speed); + return tc->def->safe; } +/* + * The resolution of the timecode. This is the number of bits per + * second at reference playback speed + */ -/* The resolution of the timecode. This is the number of bits per - * second at reference playback speed */ - -static inline double timecoder_get_resolution(struct timecoder_t *tc) +static inline double timecoder_get_resolution(struct timecoder *tc) { return tc->def->resolution * tc->speed; } +/* + * The number of revolutions per second of the timecode vinyl, + * used only for visual display + */ -/* The number of revolutions per second of the timecode vinyl, - * used only for visual display */ - -static inline double timecoder_revs_per_sec(struct timecoder_t *tc) +static inline double timecoder_revs_per_sec(struct timecoder *tc) { return (33.0 + 1.0 / 3) * tc->speed / 60; } diff --git a/src/ofxXwax.cpp b/src/ofxXwax.cpp index 358f8d5..60bc7e0 100644 --- a/src/ofxXwax.cpp +++ b/src/ofxXwax.cpp @@ -21,23 +21,27 @@ void ofxXwax::setup(unsigned int sampleRate, unsigned int bufferSize, string for this->bufferSize = bufferSize; this->format = format; + cout<, speed, sampleRate); shortBuffer.resize(nChannels * bufferSize); } void ofxXwax::update(float* input) { // convert from -1 to 1 to a 16-byte signed short integer - for (int i = 0; i < bufferSize * nChannels; i++) { + for (int i = 0; i < bufferSize*nChannels; i++) { shortBuffer[i] = input[i] * (1<<15); } timecoder_submit(&timecoder, &shortBuffer[0], bufferSize*nChannels); - float when; + double when; float curPosition = timecoder_get_position(&timecoder, &when); - + cout< shortBuffer; float pitch, velocity, relativePosition, absolutePosition; From 0d1e2265ccb98e9f6cf9bf9b40ba610ff1c33718 Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sun, 4 Nov 2012 23:40:48 -0500 Subject: [PATCH 3/7] updates WIP --- libs/xwax/timecoder.c | 262 +++++++++++++++++++++--------------------- src/ofxXwax.cpp | 2 +- 2 files changed, 131 insertions(+), 133 deletions(-) diff --git a/libs/xwax/timecoder.c b/libs/xwax/timecoder.c index ffa010e..2174a7b 100644 --- a/libs/xwax/timecoder.c +++ b/libs/xwax/timecoder.c @@ -143,14 +143,14 @@ static inline bits_t lfsr(bits_t code, bits_t taps) { bits_t taken; int xrs; - + taken = code & taps; xrs = 0; while (taken != 0x0) { xrs += taken & 0x1; taken >>= 1; } - + return xrs & 0x1; } @@ -162,9 +162,9 @@ static inline bits_t lfsr(bits_t code, bits_t taps) static inline bits_t fwd(bits_t current, struct timecode_def *def) { bits_t l; - + /* New bits are added at the MSB; shift right by one */ - + l = lfsr(current, def->taps | 0x1); return (current >> 1) | (l << (def->bits - 1)); } @@ -176,9 +176,9 @@ static inline bits_t fwd(bits_t current, struct timecode_def *def) static inline bits_t rev(bits_t current, struct timecode_def *def) { bits_t l, mask; - + /* New bits are added at the LSB; shift left one and mask */ - + mask = (1 << def->bits) - 1; l = lfsr(current, (def->taps >> 1) | (0x1 << (def->bits - 1))); return ((current << 1) & mask) | l; @@ -194,33 +194,33 @@ static int build_lookup(struct timecode_def *def) { unsigned int n; bits_t current, last; - + if (def->lookup) return 0; - + fprintf(stderr, "Building LUT for %d bit %dHz timecode (%s)\n", def->bits, def->resolution, def->desc); - + if (lut_init(&def->lut, def->length) == -1) - return -1; - + return -1; + current = def->seed; - + for (n = 0; n < def->length; n++) { /* timecode must not wrap */ if(lut_lookup(&def->lut, current) == (unsigned)-1){ - lut_push(&def->lut, current); - last = current; - current = fwd(current, def); + lut_push(&def->lut, current); + last = current; + current = fwd(current, def); if(rev(current, def) == last){ - + } } } - + def->lookup = true; - + return 0; } @@ -233,23 +233,23 @@ static int build_lookup(struct timecode_def *def) struct timecode_def* timecoder_find_definition(const char *name) { struct timecode_def *def, *end; - + def = &timecodes[0]; end = def + ARRAY_SIZE(timecodes); - + for (;;) { if (!strcmp(def->name, name)) break; - + def++; - + if (def == end) return NULL; } - + if (build_lookup(def) == -1) return NULL; - + return def; } @@ -259,10 +259,10 @@ struct timecode_def* timecoder_find_definition(const char *name) void timecoder_free_lookup(void) { struct timecode_def *def, *end; - + def = &timecodes[0]; end = def + ARRAY_SIZE(timecodes); - + while (def < end) { if (def->lookup) lut_clear(&def->lut); @@ -290,29 +290,29 @@ void timecoder_init(struct timecoder *tc, struct timecode_def *def, double speed, unsigned int sample_rate) { if(def != NULL){ - - /* A definition contains a lookup table which can be shared - * across multiple timecoders */ - + + /* A definition contains a lookup table which can be shared + * across multiple timecoders */ + if(def->lookup){ - tc->def = def; - tc->speed = speed; - - tc->dt = 1.0 / sample_rate; - tc->zero_alpha = tc->dt / (ZERO_RC + tc->dt); - - tc->forwards = 1; - init_channel(&tc->primary); - init_channel(&tc->secondary); - pitch_init(&tc->pitch, tc->dt); - - tc->ref_level = 32768.0; - tc->bitstream = 0; - tc->timecode = 0; - tc->valid_counter = 0; - tc->timecode_ticker = 0; - - tc->mon = NULL; + tc->def = def; + tc->speed = speed; + + tc->dt = 1.0 / sample_rate; + tc->zero_alpha = tc->dt / (ZERO_RC + tc->dt); + + tc->forwards = 1; + init_channel(&tc->primary); + init_channel(&tc->secondary); + pitch_init(&tc->pitch, tc->dt); + + tc->ref_level = 32768.0; + tc->bitstream = 0; + tc->timecode = 0; + tc->valid_counter = 0; + tc->timecode_ticker = 0; + + tc->mon = NULL; } } } @@ -323,9 +323,7 @@ void timecoder_init(struct timecoder *tc, struct timecode_def *def, void timecoder_clear(struct timecoder *tc) { - if(tc->mon == NULL){ - - } + timecoder_monitor_clear(tc); } /* @@ -340,14 +338,14 @@ void timecoder_clear(struct timecoder *tc) int timecoder_monitor_init(struct timecoder *tc, int size) { if(tc->mon == NULL){ - tc->mon_size = size; - tc->mon = malloc(SQ(tc->mon_size)); - if (tc->mon == NULL) { - perror("malloc"); - return -1; - } - memset(tc->mon, 0, SQ(tc->mon_size)); - tc->mon_counter = 0; + tc->mon_size = size; + tc->mon = malloc(SQ(tc->mon_size)); + if (tc->mon == NULL) { + perror("malloc"); + return -1; + } + memset(tc->mon, 0, SQ(tc->mon_size)); + tc->mon_counter = 0; } return 0; } @@ -359,8 +357,8 @@ int timecoder_monitor_init(struct timecoder *tc, int size) void timecoder_monitor_clear(struct timecoder *tc) { if(tc->mon != NULL){ - free(tc->mon); - tc->mon = NULL; + free(tc->mon); + tc->mon = NULL; } } @@ -372,7 +370,7 @@ static void detect_zero_crossing(struct timecoder_channel *ch, signed int v, double alpha) { ch->crossing_ticker++; - + ch->swapped = false; if (v > ch->zero + ZERO_THRESHOLD && !ch->positive) { ch->swapped = true; @@ -383,7 +381,7 @@ static void detect_zero_crossing(struct timecoder_channel *ch, ch->positive = false; ch->crossing_ticker = 0; } - + ch->zero += alpha * (v - ch->zero); } @@ -395,12 +393,12 @@ static void update_monitor(struct timecoder *tc, signed int x, signed int y) { int px, py, p; double v, w; - + if (!tc->mon) return; - + /* Decay the pixels already in the montior */ - + if (++tc->mon_counter % MONITOR_DECAY_EVERY == 0) { for (p = 0; p < SQ(tc->mon_size); p++) { if (tc->mon[p]){ @@ -408,15 +406,15 @@ static void update_monitor(struct timecoder *tc, signed int x, signed int y) } } } - + v = (double)x / tc->ref_level / 2; w = (double)y / tc->ref_level / 2; - + px = tc->mon_size / 2 + (v * tc->mon_size / 2); py = tc->mon_size / 2 + (w * tc->mon_size / 2); - + /* Set the pixel value to white */ - + if (px > 0 && px < tc->mon_size && py > 0 && py < tc->mon_size) tc->mon[py * tc->mon_size + px] = 0xff; } @@ -428,44 +426,44 @@ static void update_monitor(struct timecoder *tc, signed int x, signed int y) static void process_bitstream(struct timecoder *tc, signed int m) { bits_t b; - + b = m > tc->ref_level; - + /* Add it to the bitstream, and work out what we were expecting * (timecode). */ - + /* tc->bitstream is always in the order it is physically placed on * the vinyl, regardless of the direction. */ - + if (tc->forwards) { - tc->timecode = fwd(tc->timecode, tc->def); - tc->bitstream = (tc->bitstream >> 1) + tc->timecode = fwd(tc->timecode, tc->def); + tc->bitstream = (tc->bitstream >> 1) + (b << (tc->def->bits - 1)); - + } else { - bits_t mask; - - mask = ((1 << tc->def->bits) - 1); - tc->timecode = rev(tc->timecode, tc->def); - tc->bitstream = ((tc->bitstream << 1) & mask) + b; + bits_t mask; + + mask = ((1 << tc->def->bits) - 1); + tc->timecode = rev(tc->timecode, tc->def); + tc->bitstream = ((tc->bitstream << 1) & mask) + b; } - + if (tc->timecode == tc->bitstream) - tc->valid_counter++; + tc->valid_counter++; else { - tc->timecode = tc->bitstream; - tc->valid_counter = 0; + tc->timecode = tc->bitstream; + tc->valid_counter = 0; } - + /* Take note of the last time we read a valid timecode */ - + tc->timecode_ticker = 0; - + /* Adjust the reference level based on this new peak */ - + tc->ref_level = (tc->ref_level * (REF_PEAKS_AVG - 1) + m) / REF_PEAKS_AVG; - - + + } /* @@ -473,59 +471,59 @@ static void process_bitstream(struct timecoder *tc, signed int m) */ static void process_sample(struct timecoder *tc, - signed int primary, signed int secondary) + 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); - + /* If an axis has been crossed, use the direction of the crossing * to work out the direction of the vinyl */ - + if (tc->primary.swapped || tc->secondary.swapped) { bool forwards; - + if (tc->primary.swapped) { forwards = (tc->primary.positive != tc->secondary.positive); } else { forwards = (tc->primary.positive == tc->secondary.positive); } - + if (tc->def->flags & SWITCH_PHASE) - forwards = !forwards; - + forwards = !forwards; + if (forwards != tc->forwards) { /* direction has changed */ tc->forwards = forwards; tc->valid_counter = 0; } } - + /* If any axis has been crossed, register movement using the pitch * counters */ - + if (!tc->primary.swapped && !tc->secondary.swapped) - pitch_dt_observation(&tc->pitch, 0.0); + pitch_dt_observation(&tc->pitch, 0.0); else { - double dx; - - dx = 1.0 / tc->def->resolution / 4; - if (!tc->forwards) - dx = -dx; - pitch_dt_observation(&tc->pitch, dx); + double dx; + + dx = 1.0 / tc->def->resolution / 4; + if (!tc->forwards) + dx = -dx; + pitch_dt_observation(&tc->pitch, dx); } - + /* If we have crossed the primary channel in the right polarity, * it's time to read off a timecode 0 or 1 value */ - + if (tc->secondary.swapped && - tc->primary.positive == ((tc->def->flags & SWITCH_POLARITY) == 0)) + tc->primary.positive == ((tc->def->flags & SWITCH_POLARITY) == 0)) { - process_bitstream(tc, m); + process_bitstream(tc, m); } - + tc->timecode_ticker++; } @@ -538,17 +536,17 @@ static void process_sample(struct timecoder *tc, static struct timecode_def* next_definition(struct timecode_def *def) { if(def != NULL){ - - do { - def++; - - if (def > timecodes + ARRAY_SIZE(timecodes)) - def = timecodes; - - } while (!def->lookup); + + do { + def++; + + if (def > timecodes + ARRAY_SIZE(timecodes)) + def = timecodes; + + } while (!def->lookup); } - + return def; } @@ -570,8 +568,8 @@ void timecoder_cycle_definition(struct timecoder *tc) void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm) { while (npcm--) { - signed int primary, secondary; - + signed int primary, secondary; + if (tc->def->flags & SWITCH_PRIMARY) { primary = pcm[0]; secondary = pcm[1]; @@ -579,9 +577,9 @@ void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm) primary = pcm[1]; secondary = pcm[0]; } - - process_sample(tc, primary, secondary); - + + process_sample(tc, primary, secondary); + //update_monitor(tc, pcm[0], pcm[1]); pcm += TIMECODER_CHANNELS; } @@ -602,16 +600,16 @@ void timecoder_submit(struct timecoder *tc, signed short *pcm, size_t npcm) 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 (r >= 0) { if (when) *when = tc->timecode_ticker * tc->dt; return r; } } - + return -1; } diff --git a/src/ofxXwax.cpp b/src/ofxXwax.cpp index 60bc7e0..23d8073 100644 --- a/src/ofxXwax.cpp +++ b/src/ofxXwax.cpp @@ -13,7 +13,7 @@ ofxXwax::ofxXwax() ofxXwax::~ofxXwax() { timecoder_clear(&timecoder); // class - timecoder_free_lookup(); // static + //timecoder_free_lookup(); // static } void ofxXwax::setup(unsigned int sampleRate, unsigned int bufferSize, string format) { From f79ee62f83a10e13d20d4527603d7bff65ff843c Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sun, 4 Nov 2012 23:44:00 -0500 Subject: [PATCH 4/7] updates to remove hardcoded value --- src/ofxXwax.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ofxXwax.cpp b/src/ofxXwax.cpp index 23d8073..8efb028 100644 --- a/src/ofxXwax.cpp +++ b/src/ofxXwax.cpp @@ -24,7 +24,7 @@ void ofxXwax::setup(unsigned int sampleRate, unsigned int bufferSize, string for cout<, speed, sampleRate); From 21cffc2ff9845a146627061ba9347706ba7c9227 Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Mon, 5 Nov 2012 00:46:27 -0500 Subject: [PATCH 5/7] remove couts for release --- src/ofxXwax.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ofxXwax.cpp b/src/ofxXwax.cpp index 8efb028..3a7df88 100644 --- a/src/ofxXwax.cpp +++ b/src/ofxXwax.cpp @@ -21,7 +21,6 @@ void ofxXwax::setup(unsigned int sampleRate, unsigned int bufferSize, string for this->bufferSize = bufferSize; this->format = format; - cout< Date: Thu, 20 Dec 2012 00:17:34 -0500 Subject: [PATCH 6/7] major changes to the way this works --- src/ofxXwax.cpp | 38 +++++++++++++++++--------------------- src/ofxXwax.h | 14 +------------- 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/ofxXwax.cpp b/src/ofxXwax.cpp index 3a7df88..4432383 100644 --- a/src/ofxXwax.cpp +++ b/src/ofxXwax.cpp @@ -30,7 +30,14 @@ void ofxXwax::setup(unsigned int sampleRate, unsigned int bufferSize, string for shortBuffer.resize(nChannels * bufferSize); } -void ofxXwax::update(float* input) { + +// +//returns a vector of floats +// curPosition, pitch, velocity, relativePosition +// + +vector ofxXwax::update(float* input) { + vector updates; // convert from -1 to 1 to a 16-byte signed short integer for (int i = 0; i < bufferSize*nChannels; i++) { shortBuffer[i] = input[i] * (1<<15); @@ -44,6 +51,12 @@ void ofxXwax::update(float* input) { velocity = (msPerSecond * bufferSize / sampleRate) * pitch; relativePosition += velocity; + updates.push_back(curPosition); + updates.push_back(relativePosition); + updates.push_back(pitch); + updates.push_back(velocity); + + if(curPosition == invalidPosition) { absoluteValid = false; absolutePosition += velocity; @@ -51,26 +64,9 @@ void ofxXwax::update(float* input) { absoluteValid = true; absolutePosition = curPosition; } -} - -string ofxXwax::getFormat() const { - return format; -} - -float ofxXwax::getPitch() const { - return pitch; -} - -float ofxXwax::getVelocity() const { - return velocity; -} - -float ofxXwax::getRelative() const { - return relativePosition; -} - -float ofxXwax::getAbsolute() const { - return absolutePosition; + + return updates; + } bool ofxXwax::isAbsoluteValid() const { diff --git a/src/ofxXwax.h b/src/ofxXwax.h index 7456aed..ceae590 100644 --- a/src/ofxXwax.h +++ b/src/ofxXwax.h @@ -26,23 +26,11 @@ class ofxXwax { // *input is an interlaced 2-channel audio stream, which means it points to // an array that contains (bufferSize * 2) elements. - void update(float* input); + vector update(float* input); // if you need to check what the format is for display purposes string getFormat() const; - // when the record is playing forward, the pitch is +1.0 - float getPitch() const; - - // velocity is the derivative of position, milliseconds since last update - float getVelocity() const; - - // relative position does not change when you move the needle across the vinyl - float getRelative() const; - - // absolute position knows where on the record you are, avoids sticker drift - float getAbsolute() const; - // absolute position can not always be read. check to see if it's valid bool isAbsoluteValid() const; From 8fa143038fbd722188a34be47e422bfe16720d97 Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sun, 6 Jan 2013 15:41:51 -0500 Subject: [PATCH 7/7] updates for testing --- src/ofxXwax.cpp | 38 +++++++++++++++++++++----------------- src/ofxXwax.h | 14 +++++++++++++- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/ofxXwax.cpp b/src/ofxXwax.cpp index 4432383..3a7df88 100644 --- a/src/ofxXwax.cpp +++ b/src/ofxXwax.cpp @@ -30,14 +30,7 @@ void ofxXwax::setup(unsigned int sampleRate, unsigned int bufferSize, string for shortBuffer.resize(nChannels * bufferSize); } - -// -//returns a vector of floats -// curPosition, pitch, velocity, relativePosition -// - -vector ofxXwax::update(float* input) { - vector updates; +void ofxXwax::update(float* input) { // convert from -1 to 1 to a 16-byte signed short integer for (int i = 0; i < bufferSize*nChannels; i++) { shortBuffer[i] = input[i] * (1<<15); @@ -51,12 +44,6 @@ vector ofxXwax::update(float* input) { velocity = (msPerSecond * bufferSize / sampleRate) * pitch; relativePosition += velocity; - updates.push_back(curPosition); - updates.push_back(relativePosition); - updates.push_back(pitch); - updates.push_back(velocity); - - if(curPosition == invalidPosition) { absoluteValid = false; absolutePosition += velocity; @@ -64,9 +51,26 @@ vector ofxXwax::update(float* input) { absoluteValid = true; absolutePosition = curPosition; } - - return updates; - +} + +string ofxXwax::getFormat() const { + return format; +} + +float ofxXwax::getPitch() const { + return pitch; +} + +float ofxXwax::getVelocity() const { + return velocity; +} + +float ofxXwax::getRelative() const { + return relativePosition; +} + +float ofxXwax::getAbsolute() const { + return absolutePosition; } bool ofxXwax::isAbsoluteValid() const { diff --git a/src/ofxXwax.h b/src/ofxXwax.h index ceae590..7456aed 100644 --- a/src/ofxXwax.h +++ b/src/ofxXwax.h @@ -26,11 +26,23 @@ class ofxXwax { // *input is an interlaced 2-channel audio stream, which means it points to // an array that contains (bufferSize * 2) elements. - vector update(float* input); + void update(float* input); // if you need to check what the format is for display purposes string getFormat() const; + // when the record is playing forward, the pitch is +1.0 + float getPitch() const; + + // velocity is the derivative of position, milliseconds since last update + float getVelocity() const; + + // relative position does not change when you move the needle across the vinyl + float getRelative() const; + + // absolute position knows where on the record you are, avoids sticker drift + float getAbsolute() const; + // absolute position can not always be read. check to see if it's valid bool isAbsoluteValid() const;