Fixed building tool for generating drumset.h

dev
Holger Wirtz 2 years ago
parent 78c82d3dac
commit af079021a7
  1. 23
      addon/tools/convertwav.sh
  2. 359366
      addon/tools/drumset.h.orig
  3. 52
      addon/tools/wav2c.sh
  4. BIN
      addon/tools/wav2sketch
  5. 356
      addon/tools/wav2sketch.c
  6. 4
      config.h
  7. 599133
      drumset.h

@ -1,23 +0,0 @@
#!/bin/bash
WAV2SKETCH="${HOME}/Arduino-Teensy/MicroDexed/third-party/wav2sketch"
if [ ! -e "${WAV2SKETCH}" ]
then
gcc "${HOME}/Arduino-Teensy/MicroDexed/third-party/wav2sketch.c" -o "${WAV2SKETCH}"
chmod 700 "${WAV2SKETCH}"
fi
"${WAV2SKETCH}" -16
rm *.h
rm -f drumset.h
touch drumset.h
for i in `ls -1 *.cpp`
do
echo "# ${i}" >> drumset.h
cat "${i}" | grep '^[A-Za-z0-9]' >> drumset.h
echo "" >> drumset.h
rm "${i}"
done

File diff suppressed because it is too large Load Diff

@ -9,6 +9,7 @@
SOX=`which sox` SOX=`which sox`
XXD=`which xxd` XXD=`which xxd`
ASTYLE=`which astyle`
TMP="/tmp/wav2c" TMP="/tmp/wav2c"
AUDIO_BLOCK_SIZE=128 AUDIO_BLOCK_SIZE=128
DRUMSET_H="drumset.h" DRUMSET_H="drumset.h"
@ -38,6 +39,12 @@ then
exit 101 exit 101
fi fi
if [ -z "${ASTYLE}" ]
then
echo "Cannot find 'astyle' in your PATH." >&2
exit 102
fi
POSITIONAL=() POSITIONAL=()
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
key="$1" key="$1"
@ -109,7 +116,6 @@ typedef struct drum_config_s {
} drum_config_t; } drum_config_t;
enum {DRUM_NONE, DRUM_BASS, DRUM_SNARE, DRUM_HIHAT, DRUM_HANDCLAP, DRUM_RIDE, DRUM_CRASH, DRUM_LOWTOM, DRUM_MIDTOM, DRUM_HIGHTOM, DRUM_PERCUSSION}; enum {DRUM_NONE, DRUM_BASS, DRUM_SNARE, DRUM_HIHAT, DRUM_HANDCLAP, DRUM_RIDE, DRUM_CRASH, DRUM_LOWTOM, DRUM_MIDTOM, DRUM_HIGHTOM, DRUM_PERCUSSION};
EOF EOF
rm -f "${DRUMS_H}" rm -f "${DRUMS_H}"
cat >> "${DRUMS_H}" << EOF cat >> "${DRUMS_H}" << EOF
@ -159,34 +165,46 @@ do
if [ -z "${converted_files[${sample['filename']}]}" ] if [ -z "${converted_files[${sample['filename']}]}" ]
then then
basename=`echo "${sample['filename']}" | cut -d'.' -f1` basename=`echo "${sample['filename']}" | cut -d'.' -f1`
sox "${WAV_DIR}/${sample['filename']}" -c 1 -b 16 -L "${TMP}/${basename}.raw" "${SOX}" "${WAV_DIR}/${sample['filename']}" -c 1 -b 16 -L "${TMP}/${basename}.raw"
xxd -i "${TMP}/${basename}.raw" > "${TMP}/${basename}.h" "${XXD}" -c 8 -i "${TMP}/${basename}.raw" > "${TMP}/${basename}.h"
sample['len']=`grep "^unsigned int" "${TMP}/${basename}.h" | cut -d"=" -f2 | sed 's/\s*\([0-9]\+\);/\1/'` sample['len']=`grep "^unsigned int" "${TMP}/${basename}.h" | cut -d"=" -f2 | sed 's/\s*\([0-9]\+\);/\1/'`
fill_mod=`expr "${sample['len']}" % "${AUDIO_BLOCK_SIZE}"` fill_mod=`expr "${sample['len']}" % "${AUDIO_BLOCK_SIZE}"`
fill=`expr "${AUDIO_BLOCK_SIZE}" - "${fill_mod}"` fill=`expr "${AUDIO_BLOCK_SIZE}" - "${fill_mod}"`
sample_len_orig="${sample[len]}"
sample['len']=`expr "${sample['len']}" + "${fill}"` sample['len']=`expr "${sample['len']}" + "${fill}"`
sample['len']=`expr "${sample['len']}" / 2` sample['len']=`expr "${sample['len']}" / 2`
echo >> "${DRUMSET_H}"
echo "// Converted from ${sample['filename']}, length = ${sample['len']} bytes" >> "${DRUMSET_H}" echo "// Converted from ${sample['filename']}, length = ${sample['len']} bytes" >> "${DRUMSET_H}"
echo "PROGMEM const uint8_t ${sample['c_name']}[] = {" >> "${DRUMSET_H}" echo "PROGMEM const uint8_t ${sample['c_name']}[] = {" >> "${DRUMSET_H}"
grep "^ " "${TMP}/${basename}.h" >> "${DRUMSET_H}" grep "^ " "${TMP}/${basename}.h" >> "${DRUMSET_H}"
head -c -1 "${DRUMSET_H}" >> "/tmp/${DRUMSET_H}.tmp"
mv "/tmp/${DRUMSET_H}.tmp" "${DRUMSET_H}"
if (( "${fill}" > 0 )) if (( "${fill}" > 0 ))
then then
echo -n "," >> "${DRUMSET_H}" sample_fill_bytes=$(expr ${sample_len_orig} % 8 )
fill_counter=0 for i in $(seq 1 "${sample_fill_bytes}")
for i in $(seq 1 "${fill}")
do do
echo -n "0x00" >> "${DRUMSET_H}" echo -n ", 0x00" >> "${DRUMSET_H}"
let fill_counter+=1
if (( "${fill_counter}" >= 8 ))
then
echo "," >> "${DRUMSET_H}"
fill_counter=0
else
echo -n ", " >> "${DRUMSET_H}"
fi
done done
fill=$(expr ${fill} - ${sample_fill_bytes} )
if (( "${fill}" > 0 ))
then
echo "," >> "${DRUMSET_H}"
fill_cols=$(expr ${fill} / 8 )
for i in $(seq 1 "${fill_cols}")
do
echo -n " 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00" >> "${DRUMSET_H}"
if (( i < fill_cols ))
then
echo "," >> "${DRUMSET_H}"
fi
done
fi
echo >> "${DRUMSET_H}"
fi fi
echo "};" >> "${DRUMSET_H}" echo "};" >> "${DRUMSET_H}"
@ -198,7 +216,7 @@ do
sample['len']=`echo ${converted_files[${sample['filename']}]} | cut -d"," -f2` sample['len']=`echo ${converted_files[${sample['filename']}]} | cut -d"," -f2`
fi fi
# Generate drums.h # Generate drum_config
if [ ${NUM_DRUMSET_CONFIG} -gt ${MAX_NUM_DRUMSET_CONFIG} ] if [ ${NUM_DRUMSET_CONFIG} -gt ${MAX_NUM_DRUMSET_CONFIG} ]
then then
echo "/*" >> "${DRUMS_H}" echo "/*" >> "${DRUMS_H}"
@ -252,6 +270,8 @@ EOF
echo "" >> "${DRUMSET_H}" echo "" >> "${DRUMSET_H}"
cat "${DRUMS_H}" >> "${DRUMSET_H}" cat "${DRUMS_H}" >> "${DRUMSET_H}"
"${ASTYLE}" --lineend=linux --style=kr --mode=c "${DRUMSET_H}"
echo "" echo ""
echo "Created drumset.h. Copy the file to the root dicrectory of MicroDexed and don't" echo "Created drumset.h. Copy the file to the root dicrectory of MicroDexed and don't"
echo "forget to edit config.h and change the following line to the right number:" echo "forget to edit config.h and change the following line to the right number:"

Binary file not shown.

@ -1,356 +0,0 @@
// 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
// 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)));
// 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)
{
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);
for (i=0; i < chunkSize; i++) {
read_uint8(in);
}
header[3] = read_uint32(in);
}
chunkSize = read_uint32(in);
// read the audio format parameters
format = read_int16(in);
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);
format = 1;
} else if (rate == 22050) {
padlength = padding(length, 64);
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;
}
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);
fprintf(out, "// Converted from %s, using %d Hz, %s encoding\n", filename, rate,
(pcm_mode ? "16 bit PCM" : "u-law"));
fprintf(out, "PROGMEM const unsigned int AudioSample%s[%d] = {\n", samplename, arraylen);
fprintf(out, "0x%08X,", length | (format << 24));
wcount = 1;
// finally, read the audio data
while (length > 0) {
if (channels == 1) {
audio = read_int16(in);
} 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));
}
length--;
}
while (padlength > 0) {
print_byte(out, 0);
padlength--;
}
while (bcount > 0) {
print_byte(out, 0);
}
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)
{
static uint32_t buf32=0;
buf32 |= (b << (8 * bcount++));
if (bcount >= 4) {
fprintf(out, "0x%08X,", buf32);
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");
if (!fp) die("unable to read file %s", filename);
filename2samplename();
printf("converting: %s --> AudioSample%s\n", filename, samplename);
snprintf(buf, sizeof(buf), "AudioSample%s.cpp", samplename);
outc = fopen(buf, "w");
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");
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);
}

@ -56,7 +56,7 @@
// //
// Information about memory layout, etc.: https://www.pjrc.com/store/teensy41.html // Information about memory layout, etc.: https://www.pjrc.com/store/teensy41.html
#define VERSION "1.2.5" #define VERSION "1.2.6"
//************************************************************************************************* //*************************************************************************************************
//* DEVICE SETTINGS //* DEVICE SETTINGS
@ -92,7 +92,7 @@
//************************************************************************************************* //*************************************************************************************************
//* DEBUG OUTPUT SETTINGS //* DEBUG OUTPUT SETTINGS
//************************************************************************************************* //*************************************************************************************************
#define DEBUG 1 //#define DEBUG 1
//#define DEBUG_SHOW_JSON 1 //#define DEBUG_SHOW_JSON 1
#define SERIAL_SPEED 230400 #define SERIAL_SPEED 230400
#define SHOW_XRUN 1 #define SHOW_XRUN 1

599133
drumset.h

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save