improved the sound implementation
(still has too much latency, although mainly due to other parts of the menu)
This commit is contained in:
parent
5e5da4d1a8
commit
b719c4389f
20
inc/hashtable.h
Normal file
20
inc/hashtable.h
Normal file
@ -0,0 +1,20 @@
|
||||
typedef struct hashtable hashtable;
|
||||
void hashtable_destroy(hashtable *t);
|
||||
typedef struct hashtable_entry hashtable_entry;
|
||||
hashtable_entry *hashtable_body_allocate(unsigned int capacity);
|
||||
hashtable *hashtable_create();
|
||||
void hashtable_remove(hashtable *t,char *key);
|
||||
void hashtable_resize(hashtable *t,unsigned int capacity);
|
||||
void hashtable_set(hashtable *t,char *key,void *value);
|
||||
void *hashtable_get(hashtable *t,char *key);
|
||||
unsigned int hashtable_find_slot(hashtable *t,char *key);
|
||||
unsigned long hashtable_hash(char *str);
|
||||
struct hashtable {
|
||||
unsigned int size;
|
||||
unsigned int capacity;
|
||||
hashtable_entry* body;
|
||||
};
|
||||
struct hashtable_entry {
|
||||
char* key;
|
||||
void* value;
|
||||
};
|
5
inc/sound.h
Normal file
5
inc/sound.h
Normal file
@ -0,0 +1,5 @@
|
||||
void sndInit(void);
|
||||
void sndPlayBGM(char* filename);
|
||||
void sndStopAll(void);
|
||||
void sndPlaySFX(char* filename);
|
||||
void sndUpdate(void);
|
BIN
res/filesystem/bgm21.it
Normal file
BIN
res/filesystem/bgm21.it
Normal file
Binary file not shown.
159
src/hashtable.c
Normal file
159
src/hashtable.c
Normal file
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Hashtable implementation
|
||||
* (c) 2011 @marekweb
|
||||
*
|
||||
* Uses dynamic addressing with linear probing.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "hashtable.h"
|
||||
|
||||
/*
|
||||
* Interface section used for `makeheaders`.
|
||||
*/
|
||||
#if INTERFACE
|
||||
struct hashtable_entry {
|
||||
char* key;
|
||||
void* value;
|
||||
};
|
||||
|
||||
struct hashtable {
|
||||
unsigned int size;
|
||||
unsigned int capacity;
|
||||
hashtable_entry* body;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define HASHTABLE_INITIAL_CAPACITY 2
|
||||
|
||||
/**
|
||||
* Compute the hash value for the given string.
|
||||
* Implements the djb k=33 hash function.
|
||||
*/
|
||||
unsigned long hashtable_hash(char* str)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
while ((c = *str++))
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an available slot for the given key, using linear probing.
|
||||
*/
|
||||
unsigned int hashtable_find_slot(hashtable* t, char* key)
|
||||
{
|
||||
int index = hashtable_hash(key) % t->capacity;
|
||||
while (t->body[index].key != NULL && strcmp(t->body[index].key, key) != 0) {
|
||||
index = (index + 1) % t->capacity;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the item associated with the given key, or NULL if not found.
|
||||
*/
|
||||
void* hashtable_get(hashtable* t, char* key)
|
||||
{
|
||||
int index = hashtable_find_slot(t, key);
|
||||
if (t->body[index].key != NULL) {
|
||||
return t->body[index].value;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a value to the given key in the table.
|
||||
*/
|
||||
void hashtable_set(hashtable* t, char* key, void* value)
|
||||
{
|
||||
int index = hashtable_find_slot(t, key);
|
||||
if (t->body[index].key != NULL) {
|
||||
/* Entry exists; update it. */
|
||||
t->body[index].value = value;
|
||||
} else {
|
||||
t->size++;
|
||||
/* Create a new entry */
|
||||
if ((float)t->size / t->capacity > 0.8) {
|
||||
/* Resize the hash table */
|
||||
hashtable_resize(t, t->capacity * 2);
|
||||
index = hashtable_find_slot(t, key);
|
||||
}
|
||||
t->body[index].key = key;
|
||||
t->body[index].value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a key from the table
|
||||
*/
|
||||
void hashtable_remove(hashtable* t, char* key)
|
||||
{
|
||||
int index = hashtable_find_slot(t, key);
|
||||
if (t->body[index].key != NULL) {
|
||||
t->body[index].key = NULL;
|
||||
t->body[index].value = NULL;
|
||||
t->size--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new, empty hashtable
|
||||
*/
|
||||
hashtable* hashtable_create()
|
||||
{
|
||||
hashtable* new_ht = malloc(sizeof(hashtable));
|
||||
new_ht->size = 0;
|
||||
new_ht->capacity = HASHTABLE_INITIAL_CAPACITY;
|
||||
new_ht->body = hashtable_body_allocate(new_ht->capacity);
|
||||
return new_ht;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Adds all items from another table.
|
||||
*/
|
||||
hashtable* hashtable_merge(hashtable* ht, hashtable* other)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allocate a new memory block with the given capacity.
|
||||
*/
|
||||
hashtable_entry* hashtable_body_allocate(unsigned int capacity)
|
||||
{
|
||||
return (hashtable_entry*)calloc(capacity, sizeof(hashtable_entry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the allocated memory.
|
||||
* Warning: clears the table of all entries.
|
||||
*/
|
||||
void hashtable_resize(hashtable* t, unsigned int capacity)
|
||||
{
|
||||
assert(capacity >= t->size);
|
||||
unsigned int old_capacity = t->capacity;
|
||||
hashtable_entry* old_body = t->body;
|
||||
t->body = hashtable_body_allocate(capacity);
|
||||
t->capacity = capacity;
|
||||
for (int i = 0; i < old_capacity; i++) {
|
||||
if (old_body[i].key != NULL) {
|
||||
hashtable_set(t, old_body[i].key, old_body[i].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the table and deallocate it from memory. This does not deallocate the contained items.
|
||||
*/
|
||||
void hashtable_destroy(hashtable* t)
|
||||
{
|
||||
free(t->body);
|
||||
free(t);
|
||||
}
|
66
src/menu.c
66
src/menu.c
@ -36,7 +36,7 @@
|
||||
#include "menu.h"
|
||||
|
||||
//sound
|
||||
#include <mikmod.h>
|
||||
#include "sound.h"
|
||||
#include "mp3.h"
|
||||
|
||||
//debug
|
||||
@ -2567,48 +2567,18 @@ void playSound(int snd)
|
||||
{
|
||||
//no thread support in libdragon yet, sounds pause the menu for a time :/
|
||||
|
||||
//maybe global
|
||||
int v1;
|
||||
|
||||
static SAMPLE *add_sfx = NULL;
|
||||
if (snd == 1)
|
||||
add_sfx = Sample_Load("rom://ed64_mono.wav");
|
||||
sndPlaySFX("rom://ed64_mono.wav");
|
||||
|
||||
if (snd == 2)
|
||||
add_sfx = Sample_Load("rom://bamboo.wav");
|
||||
sndPlaySFX("rom://bamboo.wav");
|
||||
|
||||
if (snd == 3)
|
||||
add_sfx = Sample_Load("rom://warning.wav");
|
||||
sndPlaySFX("rom://warning.wav");
|
||||
|
||||
if (snd == 4)
|
||||
add_sfx = Sample_Load("rom://done.wav");
|
||||
sndPlaySFX("rom://done.wav");
|
||||
|
||||
MikMod_SetNumVoices(-1, 2);
|
||||
|
||||
if (!add_sfx)
|
||||
{
|
||||
MikMod_Exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
MikMod_EnableOutput();
|
||||
|
||||
audio_write_silence();
|
||||
audio_write_silence();
|
||||
|
||||
v1 = Sample_Play(add_sfx, 0, 0);
|
||||
Voice_SetVolume(v1, 100);
|
||||
|
||||
//maybe put update function into a int/vblank callback
|
||||
for (int s = 0; s < 50; s++)
|
||||
{
|
||||
MikMod_Update();
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
MikMod_DisableOutput();
|
||||
Sample_Free(add_sfx);
|
||||
}
|
||||
}
|
||||
|
||||
//draws the next char at the text input screen
|
||||
@ -3355,21 +3325,11 @@ int main(void)
|
||||
|
||||
if (sound_on)
|
||||
{
|
||||
audio_init(44100, 2);
|
||||
//load soundsystem
|
||||
audio_init(44100, 2);
|
||||
sndInit();
|
||||
|
||||
timer_init();
|
||||
|
||||
MikMod_RegisterAllDrivers();
|
||||
MikMod_RegisterAllLoaders();
|
||||
|
||||
md_mode = 0;
|
||||
md_mode |= DMODE_16BITS;
|
||||
md_mode |= DMODE_SOFT_MUSIC;
|
||||
md_mode |= DMODE_SOFT_SNDFX;
|
||||
|
||||
md_mixfreq = audio_get_frequency();
|
||||
|
||||
MikMod_Init("");
|
||||
}
|
||||
|
||||
if (!fast_boot)
|
||||
@ -3378,6 +3338,9 @@ int main(void)
|
||||
playSound(1);
|
||||
|
||||
sleep(2000); //splash screen duration
|
||||
|
||||
//todo: if bgm is enabled, we should start it...
|
||||
//sndPlayBGM("rom://bgm21.it");
|
||||
}
|
||||
|
||||
border_color_1 = translate_color(border_color_1_s);
|
||||
@ -3434,6 +3397,8 @@ int main(void)
|
||||
//system main-loop with controller inputs-scan
|
||||
while (1)
|
||||
{
|
||||
sndUpdate();
|
||||
|
||||
if (playing == 1)
|
||||
playing = update_mp3(buf_ptr, buf_size);
|
||||
|
||||
@ -4329,8 +4294,9 @@ int main(void)
|
||||
drawBoxNumber(disp, 2);
|
||||
display_show(disp);
|
||||
|
||||
printText("ALT64: v0.1.8.6.1.1", 9, 8, disp);
|
||||
printText(" ", 9, -1, disp);
|
||||
printText("Altra64: v0.1.8.6.1.2", 9, 8, disp);
|
||||
sprintf(firmware_str, "ED64 firmware: v%03x", evd_getFirmVersion());
|
||||
printText(firmware_str , 9, -1, disp);
|
||||
printText("by Saturnu", 9, -1, disp);
|
||||
printText("& JonesAlmighty", 9, -1, disp);
|
||||
printText(" ", 9, -1, disp);
|
||||
|
108
src/sound.c
Normal file
108
src/sound.c
Normal file
@ -0,0 +1,108 @@
|
||||
#include <mikmod.h>
|
||||
#include <libdragon.h> //needed for audio_get_frequency()
|
||||
#include "hashtable.h"
|
||||
|
||||
MODULE *moduleBGM = NULL;
|
||||
|
||||
/* sound effects */
|
||||
hashtable* samples = NULL;
|
||||
|
||||
/* voices */
|
||||
SBYTE voiceSFX;
|
||||
|
||||
void sndInit(void)
|
||||
{
|
||||
samples = hashtable_create();
|
||||
|
||||
/* register all the drivers */
|
||||
MikMod_RegisterAllDrivers();
|
||||
MikMod_RegisterAllLoaders();
|
||||
|
||||
/* initialize the library */
|
||||
md_mode = 0;
|
||||
md_mode |= DMODE_16BITS;
|
||||
md_mode |= DMODE_SOFT_MUSIC;
|
||||
md_mode |= DMODE_SOFT_SNDFX;
|
||||
md_mode |= DMODE_INTERP;
|
||||
|
||||
md_mixfreq = audio_get_frequency();
|
||||
|
||||
MikMod_Init("");
|
||||
|
||||
/* reserve 2 voices for sound effects */
|
||||
MikMod_SetNumVoices(-1, 2);
|
||||
|
||||
/* get ready to play */
|
||||
MikMod_EnableOutput();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void sndPlayBGM(char* filename)
|
||||
{
|
||||
if (Player_Active())
|
||||
{
|
||||
Player_Stop();
|
||||
}
|
||||
Player_Free(moduleBGM);
|
||||
moduleBGM = NULL;
|
||||
|
||||
moduleBGM = Player_Load(filename, 64, 0);
|
||||
|
||||
if (moduleBGM)
|
||||
{
|
||||
Player_Start(moduleBGM);
|
||||
Player_SetVolume(20);
|
||||
}
|
||||
}
|
||||
|
||||
void sndStopAll(void)
|
||||
{
|
||||
Voice_Stop(voiceSFX);
|
||||
Player_Stop();
|
||||
MikMod_DisableOutput();
|
||||
|
||||
int index = 0;
|
||||
while (index < samples->capacity) {
|
||||
Sample_Free(samples->body[index].value);
|
||||
index = index + 1;
|
||||
}
|
||||
|
||||
hashtable_destroy(samples);
|
||||
|
||||
Player_Free(moduleBGM);
|
||||
moduleBGM = NULL;
|
||||
|
||||
samples = hashtable_create();
|
||||
//MikMod_Exit(); //I dont think we should ever exit as that would mean reinitialising?!
|
||||
}
|
||||
|
||||
void sndPlaySFX(char* filename)
|
||||
{
|
||||
if (!Voice_Stopped(voiceSFX))
|
||||
{
|
||||
Voice_Stop(voiceSFX);
|
||||
}
|
||||
|
||||
|
||||
if (hashtable_get(samples, filename) == NULL)
|
||||
{
|
||||
hashtable_set(samples, filename, Sample_Load(filename));
|
||||
}
|
||||
|
||||
//audio_write_silence();
|
||||
Voice_SetVolume(voiceSFX, 200);
|
||||
voiceSFX = Sample_Play(hashtable_get(samples, filename), 0, 0);
|
||||
|
||||
MikMod_Update(); //force an update so that the voice is registered as playing!
|
||||
|
||||
}
|
||||
|
||||
void sndUpdate(void)
|
||||
{
|
||||
if (!Voice_Stopped(voiceSFX) || Player_Active())
|
||||
{
|
||||
MikMod_Update();
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user