]> git.sesse.net Git - c64tapwav/blobdiff - decode.cpp
Support any sample rate, not only 44100 Hz.
[c64tapwav] / decode.cpp
index 1a5ee74856c5c635e37ea434213307114964be6c..c5aa9669d0c473e8fe92911cc9cd348da3839159 100644 (file)
@@ -1,31 +1,24 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
-#include <unistd.h>
 #include <assert.h>
+#include <limits.h>
 #include <vector>
 #include <algorithm>
 
+#include "audioreader.h"
 #include "interpolate.h"
+#include "tap.h"
 
 #define BUFSIZE 4096
 #define HYSTERESIS_LIMIT 3000
-#define SAMPLE_RATE 44100
 #define C64_FREQUENCY 985248
-#define TAP_RESOLUTION 8
 
 #define SYNC_PULSE_START 1000
 #define SYNC_PULSE_END 15000
 #define SYNC_PULSE_LENGTH 378.0
 #define SYNC_TEST_TOLERANCE 1.10
 
-struct tap_header {
-       char identifier[12];
-       char version;
-       char reserved[3];
-       unsigned int data_len;
-};
-
 // between [x,x+1]
 double find_zerocrossing(const std::vector<short> &pcm, int x)
 {
@@ -41,7 +34,7 @@ double find_zerocrossing(const std::vector<short> &pcm, int x)
 
        double upper = x;
        double lower = x + 1;
-       while (upper - lower > 1e-6) {
+       while (lower - upper > 1e-3) {
                double mid = 0.5f * (upper + lower);
                if (lanczos_interpolate(pcm, mid) > 0) {
                        upper = mid;
@@ -60,15 +53,12 @@ struct pulse {
        
 int main(int argc, char **argv)
 {
+       make_lanczos_weight_table();
        std::vector<short> pcm;
-
-       while (!feof(stdin)) {
-               short buf[BUFSIZE];
-               ssize_t ret = fread(buf, 2, BUFSIZE, stdin);
-               if (ret >= 0) {
-                       pcm.insert(pcm.end(), buf, buf + ret);
-               }
-       }       
+       int sample_rate;
+       if (!read_audio_file(argv[1], &pcm, &sample_rate)) {
+               exit(1);
+       }
 
 #if 0
        for (int i = 0; i < LEN; ++i) {
@@ -106,14 +96,14 @@ int main(int argc, char **argv)
                        if (!true_pulse) {
 #if 0
                                fprintf(stderr, "Ignored down-flank at %.6f seconds due to hysteresis (%d < %d).\n",
-                                       double(i) / SAMPLE_RATE, -min_level_after, HYSTERESIS_LIMIT);
+                                       double(i) / sample_rate, -min_level_after, HYSTERESIS_LIMIT);
 #endif
                                i = j;
                                continue;
                        } 
 
                        // down-flank!
-                       double t = find_zerocrossing(pcm, i - 1) * (1.0 / SAMPLE_RATE);
+                       double t = find_zerocrossing(pcm, i - 1) * (1.0 / sample_rate);
                        if (last_downflank > 0) {
                                pulse p;
                                p.time = t;
@@ -189,4 +179,20 @@ int main(int argc, char **argv)
 
        fwrite(&hdr, sizeof(hdr), 1, stdout);
        fwrite(tap_data.data(), tap_data.size(), 1, stdout);
+
+       // Output a debug raw file with pulse detection points.
+       fp = fopen("debug.raw", "wb");
+       short one = 32767;
+       short zero = 0;
+       unsigned pulsenum = 0;
+       for (unsigned i = 0; i < pcm.size(); ++i) {
+               unsigned next_pulse = (pulsenum >= pulses.size()) ? INT_MAX : int(pulses[pulsenum].time * sample_rate);
+               if (i >= next_pulse) {
+                       fwrite(&one, sizeof(one), 1, fp);
+                       ++pulsenum;
+               } else {
+                       fwrite(&zero, sizeof(zero), 1, fp);
+               }
+       }
+       fclose(fp);
 }