Uzebox / uzebox

A retro-minimalist game console engine for the ATMega644
http://uzebox.org
125 stars 42 forks source link

Fix and add pcm2hex #135

Closed danboid closed 2 months ago

danboid commented 2 months ago

pcm2hex needs to be fixed to build correctly under Linux and added to the tools directory of this repo.

Thankfully, the Windows build of pcm2hex works with wine but Linux users shouldn't be required to install wine to use this tiny tool. In some cases (see RPi and ARM Linux users as one example) that may not be an option.

$ g++ -o pcm2hex main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:15:20: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   15 |    char *varname = "PCM_Data";
      |                    ^~~~~~~~~~
main.cpp:16:19: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   16 |    char *inname = "in.pcm";
      |                   ^~~~~~~~
main.cpp:50:7: error: ‘_fcloseall’ was not declared in this scope; did you mean ‘fcloseall’?
   50 |       _fcloseall();
      |       ^~~~~~~~~~
      |       fcloseall
main.cpp:56:7: error: ‘_fcloseall’ was not declared in this scope; did you mean ‘fcloseall’?
   56 |       _fcloseall();
      |       ^~~~~~~~~~
      |       fcloseall
main.cpp:90:4: error: ‘_fcloseall’ was not declared in this scope; did you mean ‘fcloseall’?
   90 |    _fcloseall();
      |    ^~~~~~~~~~
      |    fcloseall

https://uzebox.org/wiki/PCM_Sound_Effects

danboid commented 2 months ago

Might it make sense to rewrite pcm2hex in C to match the other tools @weber21w ? We'd likely gain nothing other than a bit of language OCD points from doing that but it seems a bit odd having one C++ tool when everything else in the Uzebox repo is written in C.

danboid commented 2 months ago

Chat Gipperty 4Oh fixed Lee's old pcm2hex code. pcm2hex now builds fine under Linux using gcc -o pcm2hex pcm2hex.c using this as pcm2hex.c:

I will add this to my current Uzebox repo in a minute.

#include <stdio.h>
#include <string.h>

// PCM2Hex - Lee Weber (D3thAdd3r) 2010
// Released under GPL 3.0 or later.

// Converts a RAW 8-bit mono PCM file (no headers) to formatted hex nicely in a PROGMEM array.
// Cool Edit and many other programs allow you to save in this format. The sample rate will depend
// on the speed you will play it back on the Uzebox via TriggerNote(). See the tutorial if you have
// questions.

int main(int argc, char *argv[]) {
    char *varname = "PCM_Data";
    char *inname = "in.pcm";
    char *outname = "PCM_out.inc";

    if (argc < 2) {
        printf("\n\tUsage: input.raw outfile[optional]\n\n" \
               "\t-v  [specify custom variable name]\n\n" \
               "\tRAW PCM 8-bit unsigned mono files supported.\n" \
               "\tEx: pcm2hex input.raw out.inc -v VarName\n\n");
        return 0;
    } else {
        inname = argv[1];
    }

    for (int i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-v")) {  // variable name
            if (i + 1 < argc) {
                varname = argv[i + 1];
                i++;
            } else {
                printf("\n\tBad variable name, using default.\n");
            }
        } else if (i == 2) {
            outname = argv[i];
        }
    }

    FILE *fin = fopen(inname, "rb");
    FILE *fout = fopen(outname, "w");

    if (fin == NULL) {
        printf("Failed to open input file.\n");
        return 1;
    }

    if (fout == NULL) {
        printf("Failed to create output file.\n");
        fclose(fin);
        return 1;
    }

    int wide = 0;
    unsigned int numbytes = 0;
    unsigned char c;
    int b;

    fprintf(fout, "const char %s[] PROGMEM = {\n", varname);

    while (fread(&b, 1, 1, fin) == 1) {
        fprintf(fout, "0x");

        b += 128;  // convert to unsigned
        c = (unsigned char)b;

        if (c < 16) {
            fprintf(fout, "0");
        }

        fprintf(fout, "%X", c);  // output hex format
        numbytes++;

        if (!feof(fin)) {
            fprintf(fout, ",");
        }

        if (++wide > 15) {  // 16 values per line
            wide = 0;
            fprintf(fout, "\n");
        }
    }

    fprintf(fout, "};\n");

    fclose(fin);
    fclose(fout);

    printf("\n\tDone. PROGMEM usage: %d bytes\n", numbytes);

    return 0;
}
danboid commented 2 months ago

I have added pcm2hex to my fork of the Uzebox repo. I created its own makefile and modified the main uzebox repo Makefile so that pcm2hex gets built by default alongside the other Uzebox tools.

https://github.com/danboid/uzebox

danboid commented 2 months ago

@artcfox sent me a link to his video on how to encode raw PCM files for use with bin2hex.

I have updated https://uzebox.org/wiki/PCM_Sound_Effects with the correct instructions and a working ffmpeg command.