-
Music and remixing it at compile time
10/10/2014 at 15:35 • 0 commentsHere you can see three functions which all playback the sound samples, just in different ways...
playback(); plays back a sample forwards.
playback_r(); plays the sample backwards.
playback_s(); plays the sample forward but at a reduced speed.
void playback(prog_uchar *sample_ptr, unsigned int length) { unsigned char bite; int col; col = 0; int i; for(i=0;i<length;i++){ bite = pgm_read_byte_near(sample_ptr + i); unsigned char mask = 1; unsigned char copy = bite; int z; for (z=0;z<8;z++) { digitalWrite(SPK_PIN, copy & mask); copy = copy >> 1; delayMicroseconds(25); } } } void playback_r(prog_uchar *sample_ptr, unsigned int length) { unsigned char bite; int col; col = 0; int i; for(i=0;i<length;i++){ bite = pgm_read_byte_near(sample_ptr + length - i); unsigned char mask = 1; unsigned char copy = bite; int z; for (z=0;z<8;z++) { digitalWrite(SPK_PIN, copy & mask); copy = copy >> 1; delayMicroseconds(25); } } } void playback_s(prog_uchar *sample_ptr, unsigned int length,unsigned int speed) { unsigned char bite; int col; col = 0; int i; for(i=0;i<length;i++){ bite = pgm_read_byte_near(sample_ptr + length - i); unsigned char mask = 1; unsigned char copy = bite; int z; for (z=0;z<8;z++) { digitalWrite(SPK_PIN, copy & mask); copy = copy >> 1; delayMicroseconds(25*speed); } } }
By mixing up and fooling around with chopping up the samples, I was able to create some interesting variations with just the 4 basic samples that I started with.
int z; for (z = 0; z < 4; z++){ playback(onebitraw_1, BC_BYTE_COUNT_1 /4); playback(onebitraw_2 + (BC_BYTE_COUNT_1 /4), BC_BYTE_COUNT_1 /4); playback_r(onebitraw_3 + (BC_BYTE_COUNT_1 /2), BC_BYTE_COUNT_1 /4); playback(onebitraw_2 + ((BC_BYTE_COUNT_1 /4) + (BC_BYTE_COUNT_1 /2)) , BC_BYTE_COUNT_1 /4); }
That code block allowed me to cut up the samples, maintain quantization and make the pattern far more interesting.
-
--input filename, is now supported
10/06/2014 at 23:47 • 0 commentsIn the demo it says --input filename doesn't work but thats now out of date, I just pushed a commit to github a few minutes ago providing code for input source file. Saves the hassle of opening your raw audio file in a hex editor and exporting to a header file.. You can now skip that step.
-
Crusher main.c description.
10/06/2014 at 16:45 • 0 commentsClick here to view the complete source on github.
All I do here to convert from 8 bit to 1 bit samples is to decide a cut off point approximately midway in the value between 0 and 255 depending on how it sounds when I preview.
In this example, we check is this current sample greater than decimal 128 ?
If it is we say then that this bit is on and off otherwise.
This is stored in an array which is used later for playback and dumping for microcontroller compatible C.
for (i = 0; i < rawDataSize; ++i) { for (j = 0; j < BUFFER; j++) { if (rawData[offset] > 128) { buf[j] = 255; } else { buf[j] = 0; } int z; for (z = 0; z < output_bitrate_divisor; z++) { offset++; } } /* snip snip snip */ }
In order to offer a sample rate down conversion I used a naive approach of just skipping samples in the source array.
Once the samples have been converted to a 1-bit resolution it's now simply a case of going through those converted samples and joining them together to make a string of 8 bits; aka 1 byte of storage.
if (mode == P_STDOUT) { /* get 8 bytes from buffer */ for (j = 0; j < BUFFER; j = j + 8) { if (process_begun) { printf(", "); } else { process_begun = 1; } if (!(obsample_bytes % 15)) { printf("\n"); } /* move through those 8 bytes and convert to binary. 0x00 = 0, 0x255 = 1. */ unsigned char converted_bits; converted_bits = 0; for (k = 0; k < 8; k++) { if (k >= BUFFER) { /* trying to read past buffer? */ fprintf(stderr, "Critical error: Tried to exceed BUFFER.\n"); exit(1); } converted_bits = converted_bits << 1; converted_bits = converted_bits + (buf[j + k] == 255); obsample_bits++; } printf("%#04X", converted_bits); obsample_bytes++; } }
-
Arduino example source code
10/06/2014 at 15:48 • 0 comments/* beverly-crusher (build 82) [http://electronoob.com] Released under the terms of the MIT license. Copyright (c) 2014 electronoob. All rights reserved. */ #include <avr/pgmspace.h> /* truncated example sample see github for working and complete example */ prog_uchar onebitraw[] PROGMEM = { 0XFF, 0XFF, 0XEF, 0XFF, 0XFB, 0XFF,... } #define BC_BIT_COUNT 23040 #define BC_BYTE_COUNT 2880 #define SPK_PIN 5 void setup(){ pinMode(SPK_PIN, OUTPUT); } void loop(){ unsigned char bite; int col; col = 0; int i; for(i=0;i<BC_BYTE_COUNT;i++){ bite = pgm_read_byte_near(onebitraw + i); /* let's break up our byte into it's constituent parts. */ unsigned char mask = 1; unsigned char copy = bite; int z; for (z=0;z<8;z++) { digitalWrite(SPK_PIN, copy & mask); copy = copy >> 1; delayMicroseconds(227); } } }
https://github.com/electronoob/beverly-crusher/blob/master/arduino/example/example.ino