libltcsmpte  0.4.4
tests/decoder.c
#include <stdio.h>
#include <math.h>
#include <tests.h>
#ifdef PRINT_AUDACITY_LABELS
void printAudacityLabel(FILE *outFile, timeu start, timeu end, char *label) {
fprintf(outFile, "" FPRNT_TIME TIME_DELIM FPRNT_TIME TIME_DELIM "%s\n", start, end, label);
}
void printAudacityLabelForSamples(FILE *outFile, SMPTEDecoder* d, size_t startInt, size_t endInt, char *label) {
timeu start, end;
start = SMPTEDecoderSamplesToSeconds(d, (long int)startInt);
end = SMPTEDecoderSamplesToSeconds(d, (long int)endInt);
printAudacityLabel(outFile, start, end, label);
}
#endif
int main(int argc, char **argv) {
int debuglevel = 2;
int sampleRate = SAMPLE_RATE;
double framesPerSec = FRAME_RATE_NUM/(double)FRAME_RATE_DEN;
sample_t sound[BUFFER_SIZE];
size_t n;
size_t total;
FILE* f;
char* filename;
SMPTEDecoder *decoder;
FrameRate *fps;
int errors;
int printMissingFrameInfo;
if (argc > 1) {
filename = argv[1];
if (argc > 2) {
sscanf(argv[2], "%i", &sampleRate);
if (argc > 3) {
sscanf(argv[3], "%lf", &framesPerSec);
}
}
} else {
printf("Usage: %s <filename> [sample rate [frame rate]]\n", argv[0]);
printf("The decoder understands " SAMPLE_TYPE " native endian raw audio at currently %i Hz sampling rate.\n", sampleRate);
return -1;
}
fps = FR_create(1, 1, FRF_NONE);
FR_setdbl(fps, framesPerSec, 1); // auto-detect drop-frames
#ifdef PRINT_AUDACITY_LABELS
debuglevel = 0;
printMissingFrameInfo = 1;
#else
printMissingFrameInfo = (debuglevel > 1);
#endif
if (debuglevel > 1)
printf("reading from: %s\n", filename);
f = fopen(filename, "r");
if (!f) {
printf("error opening %s\n", filename);
return -1;
}
double ltcFrameSamples = sampleRate / framesPerSec;
double ltcFramePlusFudge = (ltcFrameSamples * 101 / 100);
size_t ltcFrameSize = (size_t)ceil(ltcFrameSamples) * sizeof(sample_t);
if (debuglevel > 0)
{
printf("samples are %s native endian\n", SAMPLE_TYPE);
printf("sample rate = %i\n", sampleRate);
printf("frames/sec = %.2lf\n", framesPerSec);
printf("approx. SMPTE LTC frame size in bytes (samples) = %llu (%.2lf)\n\n", (unsigned long long)ltcFrameSize, ltcFrameSamples);
}
total = 0;
// Print header
#ifndef PRINT_AUDACITY_LABELS
#ifdef ENABLE_DATE
printf("%-10s %-5s ",
"Date", "Zone"
);
#endif
printf("%-11s %8s %17s"/*" %8s"*/" %4s\n",
"Timecode",
"(in ms)",
"Pos. (samples)",
//"#/F", // TEST'n'DEBUG
"Errs");
#endif
#ifdef PRINT_AUDACITY_LABELS
#define TIME_CODE_STRING_SIZE 12
char timeCodeString[TIME_CODE_STRING_SIZE];
#endif
//#define TEST_N_DEBUG_MS_OFFSET 5415000
size_t prevRead = (size_t)round(ltcFrameSamples), frameStart, frameStartFudge;
decoder = SMPTEDecoderCreate(sampleRate, fps, QUEUE_LENGTH, 0);
FR_free(fps);
do {
n = fread(sound, sizeof(sample_t), BUFFER_SIZE, f);
SMPTEDecoderWrite(decoder, sound, n, total);
if (printMissingFrameInfo) {
frameStartFudge = (size_t)round(prevRead + ltcFramePlusFudge);
if (total > frameStartFudge) {
frameStart = (size_t)round(prevRead + ltcFrameSamples);
#ifdef PRINT_AUDACITY_LABELS
printAudacityLabelForSamples(stdout, decoder, prevRead, frameStart, "No LTC frame found");
#else
#ifdef ENABLE_DATE
printf("%-16s ", "");
#endif
printf("%-20s %8lu %8lu\n", "No LTC frame at pos:", (long unsigned) prevRead, (long unsigned) frameStart);
#endif
prevRead = total;
}
}
while (SMPTEDecoderRead(decoder, &frame)) {
SMPTETime stime;
int ms;
SMPTEFrameToTime(&frame.base, &stime);
SMPTEDecoderFrameToMillisecs(decoder, &frame, &ms);
SMPTEDecoderErrors(decoder, &errors);
#ifdef PRINT_AUDACITY_LABELS
snprintf(timeCodeString, TIME_CODE_STRING_SIZE,
"%02d:%02d:%02d%c%02d",
stime.hours, stime.mins,
stime.secs, (frame.base.dfbit) ? DF_DELIMITER : NDF_DELIMITER,
stime.frame
);
printAudacityLabelForSamples(stdout, decoder, frame.startpos, frame.endpos, timeCodeString);
#else
#ifdef ENABLE_DATE
printf("%04d-%02d-%02d %s ",
((stime.years < 67) ? 2000+stime.years : 1900+stime.years),
stime.months,
stime.days,
stime.timezone
);
#endif
printf("%02d:%02d:%02d%c%02d %8d %8lu %8lu"/*" %8lu"*/" %4d\n",
stime.hours, stime.mins,
stime.secs,
(frame.base.dfbit) ? DF_DELIMITER : NDF_DELIMITER,
stime.frame,
ms, // Timecode in milliseconds
//total, // First sample of the current buffer
frame.startpos, // First sample of the LTC frame
frame.endpos, // Last(!) sample of the LTC frame
//frame.endpos - ((ms - TEST_N_DEBUG_MS_OFFSET) * sampleRate / 1000), // TEST'n'DEBUG
errors // Error count
);
#endif
prevRead = frame.endpos;
}
total += n;
} while (n);
fclose(f);
SMPTEFreeDecoder(decoder);
return 0;
}