EXTMEM and playmem

jrraines

Well-known member
Last year I was trying to play music while running Chris' uncanny eyes on a T4.1 and gave up because the sound was stuttery. I probably went wrong in not paying more attention to advice I got from smarter people here.

This year I thought I'd revisit it and try Teensy threads but as I read new stuff and reread from last year and found things happening that made me think I was actually right on the edge of stack corruption, I tried something different, which is basically working.

I'm working mostly on a mac, sometimes use a raspberry pi for some processing.
I used commands like these in terminal windows to create wav files:
Code:
for f in *.m4a; do ffmpeg -i "$f"  -ac 1 -ab 22050 -ss 0:00:01 -t 0:01:30  "${f/%m4a/wav}"; done
for f in *.mp3; do ffmpeg -i "$f"  -ac 1 -ab 22050 -ss 0:00:01 -t 0:01:30  "${f/%mp3/wav}"; done

I think those create mono (-ac 1) reduced bitrate (-ab 22050) time limited wav files.

At first I ran wav2sketch on those but then I realized that wav2sketch couldn't quite work with files that fill EXTMEM--it can put files in PROGMEM which will have less than 8megs available and EXTMEM could be 16 megs.

So I modified that to be wav2bin:
Code:
// Convert a set of WAV audio files to C data arrays for the Teensy3 Audio Library
// Copyright 2014, Paul Stoffregen (paul@pjrc.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// compile with:  gcc -O2 -Wall -o wav2sketch wav2sketch.c
//              //most of must be wrong on arm  i686-w64-mingw32-gcc -s -O2 -Wall wav2sketch.c -o wav2sketch.exe

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

uint8_t ulaw_encode(int16_t audio);
void print_byte(FILE *out, uint8_t b);
void filename2samplename(void);
uint32_t padding(uint32_t length, uint32_t block);
uint8_t read_uint8(FILE *in);
int16_t read_int16(FILE *in);
uint32_t read_uint32(FILE *in);
void die(const char *format, ...) __attribute__ ((format (printf, 1, 2)));

    static uint32_t buf32=0;

// WAV file format:
// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html

const char *filename="";
char samplename[64];
unsigned int bcount, wcount;
unsigned int total_length=0;
int pcm_mode=0;

void wav2c(FILE *in, FILE *out, FILE *outh)   //we're not gonna need outh
{
    uint32_t header[4];
    int16_t format, channels, bits;
    uint32_t rate;
    uint32_t i, length, padlength=0, arraylen;
    uint32_t chunkSize;
    int32_t audio=0;

    // read the WAV file's header
    for (i=0; i < 4; i++) {
        header[i] = read_uint32(in);
    }
    while (header[3] != 0x20746D66) {
        // skip past unknown sections until "fmt "
        chunkSize = read_uint32(in);        //so chunksize is in the wav file
        for (i=0; i < chunkSize; i++) {
            read_uint8(in);
        }
        header[3] = read_uint32(in);      //and then there's more header
    }
    chunkSize = read_uint32(in);          //and a new chunksize

    // read the audio format parameters
    format = read_int16(in);              // now we're getting audio info we'll need
    channels = read_int16(in);
    rate = read_uint32(in);
    read_uint32(in); // ignore byterate
    read_int16(in);  // ignore blockalign
    bits = read_int16(in);
    //printf("format: %d, channels: %d, rate: %d, bits %d\n", format, channels, rate, bits);
    if (format != 1)
        die("file %s is compressed, only uncompressed supported", filename);
    if (rate != 44100 && rate != 22050 && rate != 11025 /*&& rate != 8000*/ )
        die("sample rate %d in %s is unsupported\n"
          "Only 44100, 22050, 11025 work", rate, filename);
    if (channels != 1 && channels != 2)
        die("file %s has %d channels, but only 1 & 2 are supported", filename, channels);
    if (bits != 16)
        die("file %s has %d bit format, but only 16 is supported", filename, bits);

    // skip past any extra data on the WAVE header (hopefully it doesn't matter?)
    for (chunkSize -= 16; chunkSize > 0; chunkSize--) {
        read_uint8(in);
    }

    // read the data header, skip non-audio data
    while (1) {
        header[0] = read_uint32(in);
        length = read_uint32(in);
        if (header[0] == 0x61746164) break; // beginning of actual audio data
        // skip over non-audio data
        for (i=0; i < length; i++) {
            read_uint8(in);
        }
    }

    // the length must be a multiple of the data size
    if (channels == 2) {
        if (length % 4) die("file %s data length is not a multiple of 4", filename);
        length = length / 4;
    }
    if (channels == 1) {
        if (length % 1) die("file %s data length is not a multiple of 2", filename);
        length = length / 2;
    }
    if (length > 0xFFFFFF) die("file %s data length is too long", filename);
    bcount = 0;

    // AudioPlayMemory requires padding to 2.9 ms boundary (128 samples @ 44100)
    if (rate == 44100) {
        padlength = padding(length, 128);     //printed comment seemed to say I had this bitrate
        format = 1;
    } else if (rate == 22050) {
        padlength = padding(length, 64);      //This is the one I'm gonna use--format 2
        format = 2;
    } else if (rate == 11025) {
        padlength = padding(length, 32);
        format = 3;
    }
    if (pcm_mode) {
        arraylen = ((length + padlength) * 2 + 3) / 4 + 1;
        format |= 0x80;
    } else {
        arraylen = (length + padlength + 3) / 4 + 1;      //again this is me
    }
    total_length += arraylen;

    /* output a minimal header, just the length, #bits and sample rate
    fprintf(outh, "extern const unsigned int AudioSample%s[%d];\n", samplename, arraylen);    //this is going to the header file
    fprintf(out, "// Converted from %s, using %d Hz, %s encoding\n", filename, rate,
      (pcm_mode ? "16 bit PCM" : "u-law"));                                                   //and this to the .cpp file
    fprintf(out, "PROGMEM const unsigned int AudioSample%s[%d] = {\n", samplename, arraylen); //note arraylen
    fprintf(out, "0x%08X,", length | (format << 24));     //here's the first 32 bit word--I see 0x013C8FE8,
                                                          //which is the length in bytes in lower 3 bytes and format in upper byte.
                                                          //so max length would be 16 777 000 bytes, which is great!
    */
    buf32 = length | (format << 24);     //so just send the same thing to .bin file

    fwrite(&buf32,sizeof(buf32),1,out);
    wcount = 1;

    // finally, read the audio data
    while (length > 0) {
        if (channels == 1) {
            audio = read_int16(in);     //one channel--this is me
        } else {
            audio = read_int16(in);
            audio += read_int16(in);
            audio /= 2;
        }
        if (pcm_mode) {
            print_byte(out, audio);
            print_byte(out, audio >> 8);
        } else {
            print_byte(out, ulaw_encode(audio));    //this is me  so print_byte must be sending ascii hex to the file
        }
        length--;
    }
    while (padlength > 0) {
        print_byte(out, 0);
        padlength--;
    }
    while (bcount > 0) {
        print_byte(out, 0);
    }
    /*   this is formatting lines on the text file--we don't want it
    if (wcount > 0) fprintf(out, "\n");
    fprintf(out, "};\n");
    */
}


uint8_t ulaw_encode(int16_t audio)
{
    uint32_t mag, neg;

    // http://en.wikipedia.org/wiki/G.711
    if (audio >= 0) {
        mag = audio;
        neg = 0;
    } else {
        mag = audio * -1;
        neg = 0x80;
    }
    mag += 128;
    if (mag > 0x7FFF) mag = 0x7FFF;
    if (mag >= 0x4000) return neg | 0x70 | ((mag >> 10) & 0x0F);  // 01wx yz00 0000 0000
    if (mag >= 0x2000) return neg | 0x60 | ((mag >> 9) & 0x0F);   // 001w xyz0 0000 0000
    if (mag >= 0x1000) return neg | 0x50 | ((mag >> 8) & 0x0F);   // 0001 wxyz 0000 0000
    if (mag >= 0x0800) return neg | 0x40 | ((mag >> 7) & 0x0F);   // 0000 1wxy z000 0000
    if (mag >= 0x0400) return neg | 0x30 | ((mag >> 6) & 0x0F);   // 0000 01wx yz00 0000
    if (mag >= 0x0200) return neg | 0x20 | ((mag >> 5) & 0x0F);   // 0000 001w xyz0 0000
    if (mag >= 0x0100) return neg | 0x10 | ((mag >> 4) & 0x0F);   // 0000 0001 wxyz 0000
    else               return neg | 0x00 | ((mag >> 3) & 0x0F);   // 0000 0000 1wxy z000
}



// compute the extra padding needed
uint32_t padding(uint32_t length, uint32_t block)
{
    uint32_t extra;

    extra = length % block;
    if (extra == 0) return 0;
    return block - extra;
}

// pack the output bytes into 32 bit words, lsb first, and
// format the data nicely with commas and newlines
void print_byte(FILE *out, uint8_t b)
{

    buf32 |= (b << (8 * bcount++));   //we do need this packing stuff
    if (bcount >= 4) {
        //fprintf(out, "0x%08X,", buf32);     //this prints alpha--we want just send 32 bit word to .bin
        fwrite(&buf32,sizeof(buf32),1,out);
        buf32 = 0;
        bcount = 0;
        /*
        if (++wcount >= 8) {
            fprintf(out, "\n");
            wcount = 0;
        }*/
    }
}

// convert the WAV filename into a C-compatible name
void filename2samplename(void)
{
    int len, i, n;
    char c;

    len = strlen(filename) - 4;
    if (len >= sizeof(samplename)-1) len = sizeof(samplename)-1;
    for (i=0, n=0; n < len; i++) {
        c = filename[i];
        if (isalpha(c) || c == '_' || (isdigit(c) && n > 0)) {
            samplename[n] = (n == 0) ? toupper(c) : tolower(c);
            n++;
        }
    }
    samplename[n] = 0;
}


const char *title = "// Audio data converted from WAV file by wav2sketch\n\n";

int main(int argc, char **argv)
{
    DIR *dir;
    struct dirent *f;
    struct stat s;
    FILE *fp, *outc=NULL, *outh=NULL;
    char buf[128];
    int i, len;

    // By default, audio is u-law encoded to reduce the memory requirement
    // in half.  However, u-law does add distortion.  If "-16" is specified
    // on the command line, the original 16 bit PCM samples are used.
    for (i=1; i < argc; i++) {
        if (strcmp(argv[i], "-16") == 0) pcm_mode = 1;
    }
    dir = opendir(".");
    if (!dir) die("unable to open directory");
    while (1) {
        f = readdir(dir);
        if (!f) break;
        //if ((f->d_type & DT_DIR)) continue; // skip directories
        //if (!(f->d_type & DT_REG)) continue; // skip special files
        if (stat(f->d_name, &s) < 0) continue; // skip if unable to stat
        if (S_ISDIR(s.st_mode)) continue;  // skip directories
        if (!S_ISREG(s.st_mode)) continue; // skip special files
        filename = f->d_name;
        len = strlen(filename);
        if (len < 5) continue;
        if (strcasecmp(filename + len - 4, ".wav") != 0) continue;
        fp = fopen(filename, "rb");                    //open the wav file
        if (!fp) die("unable to read file %s", filename);
        filename2samplename();
        printf("converting: %s  -->  AudioSample%s\n", filename, samplename);
        snprintf(buf, sizeof(buf), "Ext%s.bin", samplename);    //puts the new filename into buf
        outc = fopen(buf, "wb");                            //here's where we open the output file we built the name in buf
        if (outc == NULL) die("unable to write %s", buf);
        //snprintf(buf, sizeof(buf), "AudioSample%s.h", samplename);
        //outh = fopen(buf, "w");
        //if (outh == NULL) die("unable to write %s\n", buf);
        //fprintf(outh, "%s", title);
        //fprintf(outc, "%s", title);
        //fprintf(outc, "#include <Arduino.h>\n");        //more header stuff he added later
        //fprintf(outc, "#include \"%s\"\n\n", buf);
        wav2c(fp, outc, outh);
        //wav2c(fp, stdout, stdout);
        fclose(outc);
        //fclose(outh);
        fclose(fp);
    }
    printf("Total data size %d bytes\n", total_length * 4);
    return 0;
}

uint8_t read_uint8(FILE *in)
{
    int c1;

    c1 = fgetc(in);
    if (c1 == EOF) die("error, end of data while reading from %s\n", filename);
    c1 &= 255;
    return c1;
}

int16_t read_int16(FILE *in)
{
    int c1, c2;

    c1 = fgetc(in);
    if (c1 == EOF) die("error, end of data while reading from %s\n", filename);
    c2 = fgetc(in);
    if (c2 == EOF) die("error, end of data while reading from %s\n", filename);
    c1 &= 255;
    c2 &= 255;
    return (c2 << 8) | c1;
}

uint32_t read_uint32(FILE *in)
{
    int c1, c2, c3, c4;

    c1 = fgetc(in);
    if (c1 == EOF) die("error, end of data while reading from %s\n", filename);
    c2 = fgetc(in);
    if (c2 == EOF) die("error, end of data while reading from %s\n", filename);
    c3 = fgetc(in);
    if (c3 == EOF) die("error, end of data while reading from %s\n", filename);
    c4 = fgetc(in);
    if (c4 == EOF) die("error, end of data while reading from %s\n", filename);
    c1 &= 255;
    c2 &= 255;
    c3 &= 255;
    c4 &= 255;
    return (c4 << 24) | (c3 << 16) | (c2 << 8) | c1;
}

void die(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    fprintf(stderr, "wav2sketch: ");
    vfprintf(stderr, format, args);
    fprintf(stderr, "\n");
    exit(1);
}

and wrote a little arduino program to go with that:
Code:
#include <SD.h>
#include <Audio.h>

//ExFatFile root;
ExFatFile song;

EXTMEM unsigned int extSong[2097151];     //8 megabytes


// GUItool: begin automatically generated code
#include <Wire.h>

AudioSynthWaveformDc     dc1;            //xy=1527.381031036377,743.0953025817871
AudioPlayMemory          playMem1;       //xy=1541.6666564941406,567.3809337615967
AudioEffectMultiply      multiply1;      //xy=1853.095272064209,685.952428817749
AudioOutputI2S           i2s1;           //xy=2034.5238167898995,688.8095310756138
AudioConnection          patchCord1(dc1, 0, multiply1, 1);
AudioConnection          patchCord2(playMem1, 0, multiply1, 0);
AudioConnection          patchCord3(multiply1, 0, i2s1, 0);
// GUItool: end automatically generated code

// GUItool: end automatically generated code


void setup(void)
{
  Serial.begin(115200);
  //while (!Serial.available() )   {};
  while (!SD.begin(BUILTIN_SDCARD))
  {
    Serial.println("...waiting for SD card...");
    delay(250);
  }
  Serial.printf("\n");
  Serial.printf("Before [0],[1],[280060],[280061] %x , %x , %x ,%x \n",extSong[0],extSong[1],extSong[280060],extSong[280601]);  size_t start=millis();

  song.open("ExtCelestialsodapop.bin",FILE_READ);
  if (!song) Serial.print("Song not found\n");
  size_t length = song.fileSize();
  Serial.printf("Song length is %d\n",length);
    song.read(extSong,length);
  song.close();
  Serial.printf("Finished disk read to ExtMem. It took %d millis\n",millis()-start);
  Serial.printf("After [0],[1],[280060],[280061] %x , % x, %x ,%x \n",extSong[0],extSong[1],extSong[280060],extSong[280061]);
  Serial.flush();
  AudioMemory(40);
   playMem1.play(extSong);
}

void loop() {
  // put your main code here, to run repeatedly:
  dc1.amplitude(analogRead(A0/1030));
  if (!playMem1.isPlaying()) playMem1.play(extSong);
}

It all seems to work and the sound is much better in the version where I included that with uncanny eyes. The first 32 bit word of the .bin file (and the way playmem works) is the encoding in the top byte and 24 bits of length. So basically the same limit as if you add 16megs of PSRAM to a T4.1 (I've just used 8 in my proof of concept testing. I don't have very good hearing and I am just using a 1" x 4" speaker with a MAX98357, so the sound might not hold up to critical listening.
 
Cool. I haven't been doing much Teensy stuff recently, but I always wanted to add sounds and such to it, and I was just thinking of adding a dfplayer chip to do the sound. If you feel inclined to, it would be nice if you published your code for adding sound.
 
What I used in the uncanny eyes is very much like what you see above. I have a separate audio.ino tab with a setupAudio() (without all the print statements above) and loopAudio() fcn. In the main uncanny eyes setup() I called setupAudio(). I did add a yield() to uncanny eyes in a couple of places, similar to what Chris suggested last year. I have a loopEyes() and a loop() that just calls loopEyes() and loopAudio() and yield().

Eventually I'll build something with a proper "box" to mount the eyes, speaker and volume control. I'll put a bunch of foil touchpads to use with fastTouch and probably load specific eyes with specific songs. Right now it is patched together in cardboard. So when you touch a foil pad, it will pause briefly to load the audio file (a minute and a half of audio seems to be less than .2 seconds) and change the eye definition. Maybe add the audio.peak function for bopping eyes to the beat or something (joystick functions should be a good guide to doing that). Furry covering??

The part that worries me going forward is the evidence that I was close to stack corruption; a subroutine wasn't returning (with print statements right before and after it). I reduced the number of eye definitions and it started returning. But the big part of the eye definitions is in PROGMEM and so reducing the number was mainly reducing the size of the array that points to them. So I can't be all that far from stack corruption again...

I have a vague recollection of a short routine to print how much was available on the stack, but I haven't been able to google it up recently. Obviously what would be most useful is to call that deep inside some library.
 
I guess the other things my original post may not have made clear is that the ffmpeg commands convert all of the .mp3 or .m4a files in a single directory to .wav and likewise ./wav2bin (like wav2sketch does for .h and .cpp files) converts all the .wav files in the current directory to .bin files. You just copy those .bin files to the SD card. One file name in the .ino program is all you have to change to use a different .bin music file--it gets the length from the SD card directory.

You could make a valid argument for doing all those conversions on the SD card itself on the principle that you should always mount a scratch monkey.
 
What I used in the uncanny eyes is very much like what you see above. I have a separate audio.ino tab with a setupAudio() (without all the print statements above) and loopAudio() fcn. In the main uncanny eyes setup() I called setupAudio(). I did add a yield() to uncanny eyes in a couple of places, similar to what Chris suggested last year. I have a loopEyes() and a loop() that just calls loopEyes() and loopAudio() and yield().
I discovered that the Teensy 4.0 did not have enough space to hold all of the eye definitions, but Teensy 4.1 does. Obviously if you have sounds, it might eat into the space.

In theory, it would be nice if we could be more dynamic, and read the eyes/sounds from either a SD card or preferably on the Teensy 4.1 use either flash memory soldered to the Teensy or use the upper 7 megabytes of program flash memory, and use MTP to move files from the PC.
 
Yesterday I posted wav2bin code. Today I played with it some more on my mac. On the mac, file names can have spaces and punctuation in them. I threw a bunch of files at it and realized that some of the names produced had extraneous trailing characters (before the .bin).

The issue is in wav2sketch as well. What is happening is that leading numbers, spaces and punctuation are trimmed but the length of the resulting name is not shortened by the number of characters that are dropped. The thing that looks easy is:
Code:
// convert the WAV filename into a C-compatible name
void filename2samplename(void)
{
    int len, i, n;
    char c;

    //for (i=0; i<sizeof(samplename); i++) samplename[i] = 0; //zero it out; it's getting extraneous stuff--not the solution

    len = strlen(filename) - 4;
    if (len >= sizeof(samplename)-1) len = sizeof(samplename)-1;    //samplename is declared [64]
    for (i=0, n=0; n < len; i++) {                                //on the mac, name might have spaces; they won't be copied and the count is wrong
        c = filename[i];
        if (isalpha(c) || c == '_' || (isdigit(c) && n > 0)) {    //trim leading numeric
            samplename[n] = (n == 0) ? toupper(c) : tolower(c);   //capitalize first char and lower case all others
            n++;
        }
        else {
          len--;                    //this seems like a bad pattern what if last char is !  or  ?
        }
    }
    samplename[n] = 0;  //this should terminate the string?
}

But my gut is telling me that is a treacherous design pattern. I suppose the code fails if a song title ends with an ! or something but I'm having trouble getting my head around it.
 
Code:
raine001@MacBook-Pro-3 wave-bin % ./wav2bin_a
converting: 05 Rhythm In The Pews.wav  -->  ExtRhythminthepewswav006.bin
converting: 06 Four Brothers.wav  -->  ExtFourbrotherswavq.bin
converting: 106 Hot Frogs on the Loose.wav  -->  ExtHotfrogsontheloosewav8extt.bin
converting: 05 Oops.wav  -->  ExtOopswav.bin
converting: 09 Cut The Cake.wav  -->  ExtCutthecakewav8e.bin
converting: 02 The Oh Of Pleasure.wav  -->  ExtTheohofpleasurewav8ex.bin
converting: The Train And The River.wav  -->  ExtThetrainandtheriverwav8.bin
converting: 08 Tiny Geometries.wav  -->  ExtTinygeometrieswavq.bin
converting: CelestialSodaPop.wav  -->  ExtCelestialsodapop.bin
converting: 13 Let's Pretend.wav  -->  ExtLetspretendwavu0.bin
converting: DuelingBanjos.wav  -->  ExtDuelingbanjos.bin
converting: TheGnome.wav  -->  ExtThegnome.bin
converting: Hallelujah.wav  -->  ExtHallelujah.bin
converting: CatacombsLinguaMortua.wav  -->  ExtCatacombslinguamortua.bin
converting: The Thought Stayed Free.wav  -->  ExtThethoughtstayedfreewav.bin
converting: 01 Englebert The Elephant.wav  -->  ExtEngleberttheelephantwav8e.bin
converting: 01 Celestial Soda Pop.wav  -->  ExtCelestialsodapopwav0e.bin
converting: 11 Java Jive.wav  -->  ExtJavajivewav0.bin
converting: NightBaldMtn.wav  -->  ExtNightbaldmtn.bin
converting: BugleCallRag.wav  -->  ExtBuglecallrag.bin
Total data size 123569232 bytes
raine001@MacBook-Pro-3 wave-bin % gcc -O2 -Wall -o wav2bin_a main_a.cpp
raine001@MacBook-Pro-3 wave-bin % ./wav2bin_a                         
converting: 05 Rhythm In The Pews.wav  -->  ExtRhythminthepews.bin
converting: 06 Four Brothers.wav  -->  ExtFourbrothers.bin
converting: 106 Hot Frogs on the Loose.wav  -->  ExtHotfrogsontheloose.bin
converting: 05 Oops.wav  -->  ExtOops.bin
converting: 09 Cut The Cake.wav  -->  ExtCutthecake.bin
converting: 02 The Oh Of Pleasure.wav  -->  ExtTheohofpleasure.bin
converting: The Train And The River.wav  -->  ExtThetrainandtheriver.bin
converting: 08 Tiny Geometries.wav  -->  ExtTinygeometries.bin
converting: CelestialSodaPop.wav  -->  ExtCelestialsodapop.bin
converting: 13 Let's Pretend.wav  -->  ExtLetspretend.bin
converting: DuelingBanjos.wav  -->  ExtDuelingbanjos.bin
converting: TheGnome.wav  -->  ExtThegnome.bin
converting: Hallelujah.wav  -->  ExtHallelujah.bin
converting: CatacombsLinguaMortua.wav  -->  ExtCatacombslinguamortua.bin
converting: The Thought Stayed Free.wav  -->  ExtThethoughtstayedfree.bin
converting: 01 Englebert The Elephant.wav  -->  ExtEngleberttheelephant.bin
converting: 01 Celestial Soda Pop.wav  -->  ExtCelestialsodapop.bin
converting: 11 Java Jive.wav  -->  ExtJavajive.bin
converting: NightBaldMtn.wav  -->  ExtNightbaldmtn.bin
converting: BugleCallRag.wav  -->  ExtBuglecallrag.bin
Total data size 123569232 bytes
 
Back
Top