diff options
| author | Raghuram Subramani <raghus2247@gmail.com> | 2022-06-19 19:47:51 +0530 | 
|---|---|---|
| committer | Raghuram Subramani <raghus2247@gmail.com> | 2022-06-19 19:47:51 +0530 | 
| commit | 4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch) | |
| tree | 65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/lib/mp3/examples/standalone/main.c | |
| parent | 0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff) | |
add circuitpython code
Diffstat (limited to 'circuitpython/lib/mp3/examples/standalone/main.c')
| -rw-r--r-- | circuitpython/lib/mp3/examples/standalone/main.c | 128 | 
1 files changed, 128 insertions, 0 deletions
| diff --git a/circuitpython/lib/mp3/examples/standalone/main.c b/circuitpython/lib/mp3/examples/standalone/main.c new file mode 100644 index 0000000..9120424 --- /dev/null +++ b/circuitpython/lib/mp3/examples/standalone/main.c @@ -0,0 +1,128 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "mp3dec.h" + +#define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN) + +int16_t audiodata[MAX_BUFFER_LEN]; + +typedef struct { +    char *ptr, *end; +} stream; +#define READ_PTR(stream) ((void*)((stream)->ptr)) +#define BYTES_LEFT(stream) ((stream)->end - (stream)->ptr) +#define CONSUME(stream, n) ((stream)->ptr += n) + +void skip_id3v2(stream* self) { +    if (BYTES_LEFT(self) < 10) { +        return; +    } +    uint8_t *data = READ_PTR(self); +    if (!( +            data[0] == 'I' && +            data[1] == 'D' && +            data[2] == '3' && +            data[3] != 0xff && +            data[4] != 0xff && +            (data[5] & 0x1f) == 0 && +            (data[6] & 0x80) == 0 && +            (data[7] & 0x80) == 0 && +            (data[8] & 0x80) == 0 && +            (data[9] & 0x80) == 0)) { +        return; +    } +    uint32_t size = (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | (data[9]); +    size += 10; // size excludes the "header" (but not the "extended header") +    CONSUME(self, size + 10); +} + +bool mp3file_find_sync_word(stream* self) { +    int offset = MP3FindSyncWord(READ_PTR(self), BYTES_LEFT(self)); +    if (offset >= 0) { +        CONSUME(self, offset); +        return true; +    } +    return false; +} + +void fatal(const char *msg) { fprintf(stderr, "%s\n", msg); exit(1); } +void perror_fatal(const char *msg) { perror(msg); exit(1); } + +bool probable_overflow(int16_t a, int16_t b) { +    if(a > 32700 && b < -32700) { +        return true; +    } else if(b > 32700 && a < -32700) { +        return true; +    } else { +        return false; +    } +} + +void look_for_overflow(int16_t *ptr, size_t os, int frame) { +    for(size_t i=2; i<os; i+=2) { +        int16_t l_old = ptr[i-2]; +        int16_t l_new = ptr[i]; +        int16_t r_old = ptr[i-1]; +        int16_t r_new = ptr[i+1]; + +        if(probable_overflow(l_old, l_new)) { +            printf("probable overflow, left  channel,  frame %5d sample %5d, %5d\n", frame, (i/2)-1, i/2); +            printf("Consecutive sample values: %5d %5d\n", l_old, l_new); +        } +        if(probable_overflow(r_old, r_new)) { +            printf("probable overflow, right channel,  frame %5d sample %5d, %5d\n", frame, (i/2)-1, i/2); +            printf("Consecutive sample values: %5d %5d\n", r_old, r_new); +        } +    } +} + +int main(int argc, char **argv) { +    if(argc != 3) { +        fprintf(stderr, "Decode MP3 into headerless LE16 stereo\n"); +        fprintf(stderr, "Usage: %s input.mp3 output.bin\n", argv[0]); +        exit(99); +    } + +    HMP3Decoder decoder = MP3InitDecoder(); + +    FILE *fi = fopen(argv[1], "rb"); +    if(!fi) perror_fatal("open"); + +    struct stat st; +    if(fstat(fileno(fi), &st) < 0) perror_fatal("fstat"); + +    stream s; +    s.ptr = malloc(st.st_size); +    if(!s.ptr) perror_fatal("malloc"); +    s.end = s.ptr + st.st_size; + +    if(fread(s.ptr, 1, st.st_size, fi) != st.st_size) perror_fatal("fread"); + +    FILE *fo = fopen(argv[2], "wb"); +    if(!fo) perror_fatal("open"); +     +    skip_id3v2(&s); + +    int frame=0; +    while(mp3file_find_sync_word(&s)) { +        MP3FrameInfo fi; +        int err = MP3GetNextFrameInfo(decoder, &fi, READ_PTR(&s)); +        if(err != ERR_MP3_NONE) fatal("MP3GetNextFrameInfo"); +        int bytes_left = (int)BYTES_LEFT(&s); +        uint8_t *inbuf = READ_PTR(&s); +        err = MP3Decode(decoder, &inbuf, &bytes_left, +                audiodata, 0); +        if(err != ERR_MP3_NONE) fatal("MP3Decode"); +        look_for_overflow(audiodata, fi.outputSamps, ++frame); +        if(fwrite(audiodata, 1, fi.outputSamps*sizeof(int16_t), fo) +                != fi.outputSamps*sizeof(int16_t)) +            perror_fatal("fwrite"); +        CONSUME(&s, BYTES_LEFT(&s) - bytes_left);  +    } + +    return 0; +} | 
