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
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); |
|
|
|
} |
|
|
|
|
|
|