1
1
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

231 lines
6.0 KiB

#include "audio.h"
#include <SDL2/SDL_keycode.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_mutex.h>
void generate_audio(void);
struct game_sounds game_sounds;
Uint8 big_hum(unsigned int t);
Uint8 func0(unsigned int t);
/**
* ----------------------------------------------------------------------------
* Audio
* ----------------------------------------------------------------------------
*
* Sound-effects are generated at startup, and synthesised using 8-bit
* integer overflow a la bytebeat https://arxiv.org/pdf/1112.1368.pdf.
*
* see generate_audio()
*
*/
int mute = false;
void fill_audio(void *func, Uint8 *stream, int len) {
Uint8 (*wavegen)(unsigned int) = func;
unsigned int t = 1;
for(int i = 0; i < len; i++,t++) {
stream[i] = wavegen(t);
}
}
void callbackfn3(void *unused, Uint8 *stream, int len) {
static int t = 1;
for(int i = 0; i < len; i++,t++) {
stream[i] = big_hum(t);
stream[i] = 0;
}
}
void start_audio(void) {
if (Mix_OpenAudio(G_AUDIO_SFREQ,AUDIO_S8,1,G_AUDIO_BSIZE) < 0) {
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
exit(1);
}
if (Mix_AllocateChannels(20) < 0) {
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
}
generate_audio();
}
void
play_game_sound(Mix_Chunk *chunk, int len, int channel)
{
if (mute || Mix_Playing(channel)) {
return;
}
if(Mix_PlayChannelTimed(channel, chunk, -1, len) < 0)
fprintf(stderr, "Unable to play audio: %s\n", SDL_GetError());
//Mix_FadeInChannelTimed(channel, chunk, -1, 1, len);
}
Uint8
pitchshift_hit(unsigned int t, void *arg)
{
double *hitt = arg;
double hit = *hitt;
hit = 6 - hit;
int lower = 10 + 2 * (hit > 6 ? 6 : hit);
int higher = 1 + (hit > 6 ? 6 : hit);
const double R=8000; // sample rate (samples per second)
const double C=125; // frequency of middle-C (hertz)
const double F=R/256; // bytebeat frequency of 1*t due to 8-bit truncation (hertz)
const double V=127; // a volume constant
double volume = (((t / 3000) > 2) ? 2 : t / 3000);
return ((sin(t*2*M_PI/R*(125 + hit))+1)*10 + (sin(t*2*M_PI/R*(250 + hit))+1)*(50 + hit) + (sin(t*2*M_PI/R*(900 + hit))+1)*100 + (sin(t*2*M_PI/R*(150+ hit))+1)*5) ;
}
void
synthplay_now(Uint8 (*bbgen)(unsigned int t, void *), void *arg, int len)
{
static Mix_Chunk *new_chunk = NULL;
if (Mix_Playing(1)) {
return;
}
if (new_chunk)
Mix_FreeChunk(new_chunk);
int generate_len = len * (512);
Uint8 raw_data[generate_len];
unsigned int t = 1;
for(int i = 0; i < generate_len; i++,t++) {
raw_data[i] = bbgen(t, arg);
}
new_chunk = Mix_QuickLoad_RAW(raw_data, generate_len);
Mix_PlayChannelTimed(1, new_chunk, -1, len);
}
void callbackfn2(void *unused, Uint8 *stream, int len) {
static int t = 1;
int i;
int yeet = rand();
for(i=0; i < len; i++,t++) {
stream[i] = func0(t);
}
}
void callbackfn(void *unused, Uint8 *stream, int len)
{
static int t = 0;
int i;
int yeet = rand();
for( i=0; i < len; i++,t++) {
/*
stream[i] = (t*5&(t>>7))|(t*3&(t>>8));
*/
//stream[i] = (( t >> 10 ) & 42) * t;
stream[i] = (t & yeet) % 73;
}
}
/* Waveform Generators */
Uint8 big_hum(unsigned int t) {
return ( (sin(t*2*3.14159265/8000*200)+1) * 20) + ( (sin(t*2*3.14159265/8000*110)+1) * 20) + ( (sin(t*2*3.14159265/8000*230)+1) * 20) + ( (sin((t % 80)*2*3.14159265/8000 * 6)+1) * 12);
}
unsigned int sine_wave_sound(unsigned int t) {
const double R=8000; // sample rate (samples per second)
const double C=261.625565; // frequency of middle-C (hertz)
const double F=R/256; // bytebeat frequency of 1*t due to 8-bit truncation (hertz)
const double V=127; // a volume constant
return (sin(t*2*M_PI/R*C)+1)*V;
}
Uint8 winch_sound(unsigned t) {
return (((t % 80) | (t % 36) | (6 * (t % 6))) + 20) * 1.6;
return ((t % 80) | (t % 36) | (6 * (t % 6)));
}
Uint8 beat_2(unsigned t) {
return ((((t % 250) / 2)) | (t % 129)) % 110;
}
Uint8 func0(unsigned t) {
int note = 18;
if (!(t % 1240)) {
note = (1 + rand()) % 18 + 1;
}
fflush(stdout);
return (t % note);
}
Uint8 func1(unsigned int t) {
int note = 10;
if (!(t % 8000)) {
note = (1 + rand()) % 10 + 5;
}
return ((t & 110) % 73 | (t % 1711));
}
Uint8 collision_test(unsigned int t) {
// try not to loop
return ((t < 3000) * ((t % 5) * (3000 - t % 3000) * 0.00351))
+ ((t < 3500) * ((3500 - t % 3500)) * 0.0002 * (t % 14));
return ((t < 3000) * ((t % 5) * (3000 - t % 3000) * 0.00351))
+ ((4000 - t % 4000) * 0.0003 * (t % 128))
+ ((t < 3500) * ((3500 - t % 3500)) * 0.0002 * (t % 64)); // has a big low sound
return (t % 4) * (4000 - t % 4000) * 0.01;
}
Uint8 boop_noise(unsigned int t) {
return ((t >> 10) & 42) * t;
}
Uint8 rope_attach(unsigned int t) {
return (((2000 - (t % 2000)))/40 * (t % 20) | (t % 44) + 20) * 1.6;
}
/*
* Called by startgame() to initialise sound effects.
*/
void generate_audio(void) {
const int sfx_len_ms = 1000;
unsigned int sfx_len = (G_AUDIO_SFREQ/1000) * G_AUDIO_BSIZE * sfx_len_ms;
sfx_len = G_AUDIO_BSIZE;
Uint8 *raw_data = malloc(sfx_len);
fill_audio(winch_sound, raw_data, sfx_len);
game_sounds.rope_pull = Mix_QuickLoad_RAW(raw_data, sfx_len);
Mix_Volume(BC_ROPE_PULL, MIX_MAX_VOLUME * 0.3);
Uint8 *raw_data2 = malloc(sfx_len);
fill_audio(collision_test, raw_data2, sfx_len);
game_sounds.collision = Mix_QuickLoad_RAW(raw_data2, sfx_len);
Mix_Volume(BC_COLLISION, MIX_MAX_VOLUME * 1.2);
Uint8 *raw_data3 = malloc(sfx_len);
fill_audio(big_hum, raw_data3, sfx_len);
game_sounds.background = Mix_QuickLoad_RAW(raw_data3, sfx_len);
Mix_Volume(BC_MUSIC, MIX_MAX_VOLUME * 0.1);
Uint8 *raw_data4 = malloc(sfx_len);
fill_audio(rope_attach, raw_data4, sfx_len);
game_sounds.rope_attach = Mix_QuickLoad_RAW(raw_data4, sfx_len);
Mix_Volume(BC_ROPE_ATTACH, MIX_MAX_VOLUME * 0.1);
}