Skip to content
This repository has been archived by the owner on Feb 25, 2024. It is now read-only.

Commit

Permalink
Initial sound support
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdanielps committed Jan 17, 2016
1 parent 5295add commit b837bd2
Show file tree
Hide file tree
Showing 8 changed files with 4,999 additions and 7 deletions.
50 changes: 47 additions & 3 deletions include/allegro_compat.h
Expand Up @@ -2,6 +2,7 @@
#define ALLEGRO_COMPAT_H_

#include <stdint.h>
#include <stdbool.h>

// A reimplementation of some allegro functions and structures
// Hopefully we won't need it in the future
Expand All @@ -10,23 +11,66 @@
#define D_OK 0
#define D_EXIT 1

typedef struct BITMAP { // A bitmap structure
int w, h; // Width and height in pixels
void *dat; // The memory we allocated for the bitmap
#define PLAYMODE_PLAY 0
#define PLAYMODE_LOOP 1
#define PLAYMODE_FORWARD 0
#define PLAYMODE_BACKWARD 2
#define PLAYMODE_BIDIR 4

#define DIGI_AUTODETECT -1 // For passing to install_sound()
#define DIGI_NONE 0

#define MIDI_AUTODETECT -1
#define MIDI_NONE 0

// A bitmap structure
typedef struct {
int w, h; // Width and height in pixels
void *dat; // The memory we allocated for the bitmap
unsigned char **line;
} BITMAP;

typedef struct {
unsigned char r, g, b;
} RGB;

typedef struct {
int bits; // 8 or 16
int stereo; // Sample type flag
int freq; // Sample frequency
int priority; // 0-255
unsigned long len; // Length (in samples)
unsigned long loop_start; // Loop start position
unsigned long loop_end; // Loop finish position
unsigned long param; // For internal use by the driver
void* data; // Raw sample data
} SAMPLE;

void masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
void masked_stretch_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_w, int source_h, int dest_x, int dest_y, int dest_w, int dest_h);

BITMAP *create_bitmap(int w, int h);
void destroy_bitmap(BITMAP *bitmap);
void clear_to_color(BITMAP *bitmap, int color);

int install_sound(int digi, int midi, const char *config_path);
void remove_sound();
SAMPLE* create_sample(int bits, int stereo, int freq, int len);
void destroy_sample(SAMPLE* spl);
int allocate_voice(SAMPLE* spl);
void voice_set_playmode(int voice, int playmode);
void voice_stop(int voice);
void deallocate_voice(int voice);
void voice_sweep_frequency(int voice, int time, int endfreq);
void voice_set_position(int voice, int position);
void voice_start(int voice);
void voice_set_volume(int voice, int volume);
int voice_get_volume(int voice);
void voice_set_pan(int voice, int pan);
void voice_ramp_volume(int voice, int time, int endvol);
void voice_set_frequency(int voice, int frequency);
int voice_get_frequency(int voice);

// Not exactly allegro stuff, but kinda compatible.
// menu_item_t is exactly the same as a MENU struct in allegro, but it's used
// differently.
Expand Down
4,103 changes: 4,103 additions & 0 deletions include/vb_lfsr.h

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions include/vb_sound.h
@@ -0,0 +1,71 @@
////////////////////////////////////////////////////////////////
// Defines for the VB Sound system
// put them here because its not very portable (yet)
#ifndef VB_SOUND_H_
#define VB_SOUND_H_

#include <stdbool.h>

//wave data number does not necessarily correspond to channel number
//(value set in Waveform RAM Address)
#define WAVEDATA1 0x01000000 //only 6 bits of 32 bit addressed used
#define WAVEDATA2 0x01000080 //only 6 bits of 32 bit addressed used
#define WAVEDATA3 0x01000100 //only 6 bits of 32 bit addressed used
#define WAVEDATA4 0x01000180 //only 6 bits of 32 bit addressed used
#define WAVEDATA5 0x01000200 //only 6 bits of 32 bit addressed used
#define MODDATA 0x01000280 //only 8 bits of 32 bit addressed used

#define S1INT 0x01000400
#define S1LRV 0x01000404
#define S1FQL 0x01000408
#define S1FQH 0x0100040C
#define S1EV0 0x01000410
#define S1EV1 0x01000414
#define S1RAM 0x01000418

#define S2INT 0x01000440
#define S2LRV 0x01000444
#define S2FQL 0x01000448
#define S2FQH 0x0100044C
#define S2EV0 0x01000450
#define S2EV1 0x01000454
#define S2RAM 0x01000458

#define S3INT 0x01000480
#define S3LRV 0x01000484
#define S3FQL 0x01000488
#define S3FQH 0x0100048C
#define S3EV0 0x01000490
#define S3EV1 0x01000494
#define S3RAM 0x01000498

#define S4INT 0x010004C0
#define S4LRV 0x010004C4
#define S4FQL 0x010004C8
#define S4FQH 0x010004CC
#define S4EV0 0x010004D0
#define S4EV1 0x010004D4
#define S4RAM 0x010004D8

#define S5INT 0x01000500
#define S5LRV 0x01000504
#define S5FQL 0x01000508
#define S5FQH 0x0100050C
#define S5EV0 0x01000510
#define S5EV1 0x01000514
#define S5RAM 0x01000518
#define S5SWP 0x0100051C

#define S6INT 0x01000540
#define S6LRV 0x01000544
#define S6FQL 0x01000548
#define S6FQH 0x0100054C
#define S6EV0 0x01000550
#define S6EV1 0x01000554
#define SSTOP 0x01000580

void sound_init();
void sound_update(int reg);
void sound_close();

#endif //VB_SOUND_H_
2 changes: 1 addition & 1 deletion jni/Android.mk
Expand Up @@ -5,7 +5,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := r3Ddragon
LOCAL_SRC_FILES := ../source/common/allegro_compat.c ../source/arm-linux/main.c ../source/common/drc_core.c ../source/common/drc_exec.s ../source/common/drc_static.s \
../source/common/rom_db.c ../source/common/v810_cpu.c ../source/common/v810_ins.c ../source/common/v810_mem.c ../source/common/vb_dsp.c ../source/common/vb_gui.c \
../source/common/vb_set.c ../source/arm-linux/arm_utils.c ../source/common/inih/ini.c
../source/common/vb_set.c ../source/common/vb_sound.c ../source/arm-linux/arm_utils.c ../source/common/inih/ini.c
LOCAL_C_INCLUDES := include source/common/inih
TARGET_ARCH := arm
TARGET_ARCH_ABI := armeabi
Expand Down
3 changes: 3 additions & 0 deletions source/3ds/main.c
Expand Up @@ -9,6 +9,7 @@
#include "drc_core.h"
#include "vb_dsp.h"
#include "vb_set.h"
#include "vb_sound.h"
#include "vb_gui.h"
#include "rom_db.h"

Expand Down Expand Up @@ -193,6 +194,7 @@ int main() {
}

v810_reset();
sound_init();
drc_init();

clearCache();
Expand Down Expand Up @@ -257,6 +259,7 @@ int main() {

exit:
V810_DSP_Quit();
sound_close();
drc_exit();

hbHaxExit();
Expand Down
181 changes: 181 additions & 0 deletions source/common/allegro_compat.c
Expand Up @@ -15,6 +15,8 @@
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

// Graphics stuff

void masked_blit(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h) {
int x, y;

Expand Down Expand Up @@ -90,6 +92,185 @@ void clear_to_color(BITMAP *bitmap, int color) {
}
}

// Sound stuff

typedef struct {
bool playing;
int pos;
int rate;
float vol;
float pan;
SAMPLE* spl;
#ifdef _3DS
ndspWaveBuf ndsp_buf;
#endif
} snd_channel;

snd_channel* channels;
u32 available;

int install_sound(int digi, int midi, const char *config_path) {
#ifdef _3DS
#if DEBUGLEVEL == 0
if (ndspInit())
return -1;
#endif
#endif
available = 0x00FFFFFF;

channels = linearAlloc(32*sizeof(snd_channel));
memset(channels, 0, 32*sizeof(snd_channel));

return 0;
}

void remove_sound() {
linearFree(channels);
#ifdef _3DS
ndspExit();
#endif
}

SAMPLE* create_sample(int bits, int stereo, int freq, int len) {
SAMPLE* spl;

spl = linearAlloc(sizeof(SAMPLE));
if (!spl)
return NULL;

spl->bits = bits;
spl->stereo = stereo;
spl->freq = freq;
spl->priority = 128;
spl->len = len;
spl->loop_start = 0;
spl->loop_end = len;
spl->param = 0;

spl->data = linearAlloc(len * ((bits==8) ? 1 : sizeof(short)) * ((stereo) ? 2 : 1));
if (!spl->data) {
free(spl);
return NULL;
}

return spl;
}

void destroy_sample(SAMPLE *spl) {
if (spl) {
if (spl->data)
linearFree(spl->data);
linearFree(spl);
}
}

int allocate_voice(SAMPLE* spl) {
int i;

for (i = 0; i < 32; i++) {
if ((available>>i) & 1) {
available &= ~(1<<i);
break;
}
}

if (i == 32)
return -1;

channels[i].playing = false;
channels[i].pos = 0;
channels[i].rate = spl->freq;
channels[i].spl = spl;

return i;
}

void voice_set_playmode(int voice, int playmode) {
#ifdef _3DS
channels[voice].ndsp_buf.looping = (playmode == PLAYMODE_LOOP);
#endif
}

void voice_stop(int voice) {
#ifdef _3DS
ndspChnWaveBufClear(voice);
#endif
channels[voice].playing = false;
}

void deallocate_voice(int voice) {
available |= 1<<voice;
}

void voice_sweep_frequency(int voice, int time, int endfreq) {
// TODO: Actually sweep
voice_set_frequency(voice, endfreq);
}

void voice_set_position(int voice, int position) {
channels[voice].pos = position;
if (channels[voice].playing && position == 0)
voice_start(voice);
}

void voice_start(int voice) {
// Don't play the sound if the voice isn't allocated
if (available & (1<<voice))
return;
if (!channels[voice].spl || !channels[voice].spl->data)
return;

channels[voice].playing = true;
#ifdef _3DS
memset(&channels[voice].ndsp_buf, 0, sizeof(ndspWaveBuf));
channels[voice].ndsp_buf.data_vaddr = channels[voice].spl->data;
channels[voice].ndsp_buf.nsamples = channels[voice].spl->len;
channels[voice].ndsp_buf.looping = true;
channels[voice].ndsp_buf.status = NDSP_WBUF_FREE;

ndspChnReset(voice);
ndspChnSetFormat(voice, (channels[voice].spl->bits == 8) ? NDSP_FORMAT_MONO_PCM8 : NDSP_FORMAT_MONO_PCM16);
ndspChnSetInterp(voice, NDSP_INTERP_NONE);
ndspChnSetRate(voice, channels[voice].spl->freq);
ndspChnWaveBufAdd(voice, &channels[voice].ndsp_buf);
#endif
}

void voice_set_volume(int voice, int volume) {
float mix[12];
int i;
channels[voice].vol = volume/255.0f;
#ifdef _3DS
for (i = 0; i < 12; i++)
mix[i] = channels[voice].vol;
ndspChnSetMix(voice, mix);
#endif
}

int voice_get_volume(int voice) {
return (int)(channels[voice].vol*255);
}

void voice_set_pan(int voice, int pan) {
channels[voice].pan = pan/128.0f - 1;
}

void voice_ramp_volume(int voice, int time, int endvol) {
// TODO: Actually ramp
voice_set_volume(voice, endvol);
}

void voice_set_frequency(int voice, int frequency) {
channels[voice].rate = frequency;
#ifdef _3DS
ndspChnSetRate(voice, frequency);
#endif
}

int voice_get_frequency(int voice) {
return channels[voice].rate;
}

// The following is not exactly allegro stuff

void toggle3D() {
Expand Down

0 comments on commit b837bd2

Please sign in to comment.