beat

Arrange audio samples into something bigger
git clone https://git.ce9e.org/beat.git

commit
400aebaa8e6b0942aad55146b1f79008aa368be2
parent
a5eedb8e9de8c0ddfdca53fb6d769f5e922bb123
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2019-12-17 14:27
use more than one buffer

assumes that input is ordered

Diffstat

M beat.c 79 +++++++++++++++++++++++++++++++++++++++++++------------------

1 files changed, 56 insertions, 23 deletions


diff --git a/beat.c b/beat.c

@@ -2,11 +2,16 @@
    2     2 #include <string.h>
    3     3 #include <sndfile.h>
    4     4 
   -1     5 #define MIN(A, B) ((A) < (B) ? (A) : (B))
   -1     6 
    5     7 struct context {
    6     8     int samplerate;
    7     9     int frames_per_beat;  // samplerate * 60 / bpm
    8    10     int frames;
   -1    11     int buf_cur;
   -1    12     size_t buf_len;
    9    13     float *buf;
   -1    14     float *buf2;
   10    15 };
   11    16 
   12    17 void add_file_at_beat(const char *path, int beat, struct context ctx) {
@@ -21,37 +26,29 @@ void add_file_at_beat(const char *path, int beat, struct context ctx) {
   21    26 
   22    27     while (1) {
   23    28         int count = sf_readf_float(sndfile, fbuf, ibs);
   24    -1 
   25    -1         if (pos + count >= ctx.frames) {
   26    -1             count = ctx.frames - pos - 1;
   27    -1         }
   -1    29         count = MIN(count, ctx.frames - pos - 1);
   -1    30         int rel_pos = pos - ctx.buf_cur * ctx.buf_len;
   28    31 
   29    32         if (count <= 0) break;
   30    33 
   31    34         for (int i = 0; i < count; ++i) {
   32    35             pos += 1;
   33    -1             ctx.buf[pos] += fbuf[i];
   -1    36             rel_pos += 1;
   -1    37             if (rel_pos >= 2 * ctx.buf_len) {
   -1    38                 printf("dropping %s at %i\n", path, pos);
   -1    39                 sf_close(sndfile);
   -1    40                 return;
   -1    41             } else if (rel_pos >= ctx.buf_len) {
   -1    42                 ctx.buf2[rel_pos - ctx.buf_len] += fbuf[i];
   -1    43             } else {
   -1    44                 ctx.buf[rel_pos] += fbuf[i];
   -1    45             }
   34    46         }
   35    47     }
   36    48 
   37    49     sf_close(sndfile);
   38    50 }
   39    51 
   40    -1 void write_file(const char *path, struct context ctx) {
   41    -1     SF_INFO sfinfo;
   42    -1 
   43    -1     sfinfo.channels = 1;
   44    -1     sfinfo.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
   45    -1     sfinfo.frames = ctx.frames;
   46    -1     sfinfo.samplerate = ctx.samplerate;
   47    -1     sfinfo.sections = 1;
   48    -1     sfinfo.seekable = 1;
   49    -1 
   50    -1     SNDFILE *sndfile = sf_open(path, SFM_WRITE, &sfinfo);
   51    -1     sf_writef_float(sndfile, ctx.buf, ctx.frames);
   52    -1     sf_close(sndfile);
   53    -1 }
   54    -1 
   55    52 int main(int argc, char **argv) {
   56    53     if (argc < 6 || argc % 2 != 1) {
   57    54         printf("Usage: beat OUTFILE SAMPLERATE FRAMES_PER_BEAT BEATS BEAT INFILE [BEAT INFILE…]\n");
@@ -64,15 +61,51 @@ int main(int argc, char **argv) {
   64    61     ctx.frames_per_beat = atoi(argv[3]);
   65    62     ctx.frames = atoi(argv[4]) * ctx.frames_per_beat;
   66    63 
   67    -1     float buf[ctx.frames];
   68    -1     memset(buf, 0, ctx.frames * sizeof(float));
   -1    64     ctx.buf_len = MIN(ctx.frames / 4, 1 << 18);
   -1    65     ctx.buf_cur = 0;
   -1    66 
   -1    67     float buf[ctx.buf_len];
   -1    68     memset(buf, 0, ctx.buf_len * sizeof(float));
   69    69     ctx.buf = buf;
   70    70 
   -1    71     float buf2[ctx.buf_len];
   -1    72     memset(buf2, 0, ctx.buf_len * sizeof(float));
   -1    73     ctx.buf2 = buf2;
   -1    74 
   -1    75     SF_INFO sfinfo;
   -1    76     sfinfo.channels = 1;
   -1    77     sfinfo.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
   -1    78     sfinfo.frames = ctx.frames;
   -1    79     sfinfo.samplerate = ctx.samplerate;
   -1    80     sfinfo.sections = 1;
   -1    81     sfinfo.seekable = 1;
   -1    82 
   -1    83     SNDFILE *sndfile = sf_open(argv[1], SFM_WRITE, &sfinfo);
   -1    84 
   71    85     for (int i = 5; i + 1 < argc; i += 2) {
   72    86         int beat = atoi(argv[i]);
   73    87         char *path = argv[i + 1];
   -1    88 
   -1    89         if (beat * ctx.frames_per_beat >= (ctx.buf_cur + 1) * ctx.buf_len) {
   -1    90             sf_writef_float(sndfile, ctx.buf, ctx.buf_len);
   -1    91             memset(ctx.buf, 0, ctx.buf_len * sizeof(float));
   -1    92 
   -1    93             float *tmp = ctx.buf;
   -1    94             ctx.buf = ctx.buf2;
   -1    95             ctx.buf2 = tmp;
   -1    96             ctx.buf_cur += 1;
   -1    97         }
   -1    98 
   74    99         add_file_at_beat(path, beat, ctx);
   75   100     }
   76   101 
   77    -1     write_file(argv[1], ctx);
   -1   102     int rest = ctx.frames - ctx.buf_cur * ctx.buf_len;
   -1   103     if (rest > ctx.buf_len) {
   -1   104         sf_writef_float(sndfile, ctx.buf, ctx.buf_len);
   -1   105         sf_writef_float(sndfile, ctx.buf2, rest - ctx.buf_len);
   -1   106     } else {
   -1   107         sf_writef_float(sndfile, ctx.buf, rest);
   -1   108     }
   -1   109 
   -1   110     sf_close(sndfile);
   78   111 }