Added mixer and sound (c side)

This commit is contained in:
rnlf
2017-01-22 01:01:24 +01:00
parent d78f203674
commit 5f6daa497f
6 changed files with 195 additions and 19 deletions

View File

@@ -20,12 +20,15 @@
#include "image.h"
#include "palette.h"
#include "package.h"
#include "soundblaster.h"
#include "mixer.h"
static lua_State *L;
static void deinit(void) {
/* Deinit and clear up everything. Called at exit */
soundblaster_deinit();
vga_deinit();
keyboard_deinit();
lua_close(L);
@@ -59,6 +62,7 @@ int main(int argc, char **argv) {
palette_init();
keyboard_init();
mouse_init();
soundblaster_init(mixer_getNextBlock);
/* Init lua */
L = luaL_newstate();

90
src/mixer.c Normal file
View File

@@ -0,0 +1,90 @@
#include <string.h>
#include <dos.h>
#include <stdbool.h>
#include "mixer.h"
#include "soundblaster.h"
#define MIXER_MAX_SOUNDS 8
typedef struct {
int offset;
sound_t const *sound;
} mixed_sound_t;
static mixed_sound_t sounds[MIXER_MAX_SOUNDS];
static int activeSounds = 0;
static int16_t data[SOUNDBLASTER_SAMPLES_PER_BUFFER] = {0};
static bool canmix = true;
void mixer_init(void) {
}
int16_t const * mixer_getNextBlock(void) {
canmix = true;
return data;
}
void mixer_play(sound_t const *sound) {
if(activeSounds == MIXER_MAX_SOUNDS) {
// TODO Replace older sound with new one instead?
return;
}
for(int i = 0; i < activeSounds; ++i) {
if(sounds[i].sound == sound) {
sounds[i].offset = 0;
return;
}
}
sounds[activeSounds].offset = 0;
sounds[activeSounds].sound = sound;
++activeSounds;
}
static inline int16_t mix(int32_t a, int32_t b) {
int32_t res = a + b;
if(res > INT16_MAX)
res = INT16_MAX;
if(res < INT16_MIN)
res = INT16_MIN;
return res;
}
void mixer_mix(void) {
if(!canmix)
return;
memset(data, 0, SOUNDBLASTER_SAMPLES_PER_BUFFER);
for(int i = 0; i < activeSounds; ++i) {
mixed_sound_t *snd = sounds + i;
int len = snd->sound->sampleCount;
int16_t const* soundBuf = snd->sound->samples;
if(len > SOUNDBLASTER_SAMPLES_PER_BUFFER) {
len = SOUNDBLASTER_SAMPLES_PER_BUFFER;
}
for(int offset = 0; offset < len; ++offset) {
data[offset] = mix(data[offset], soundBuf[offset]);
}
snd->offset += len;
}
for(int i = activeSounds-1; i >= 0; --i) {
mixed_sound_t *snd = sounds + i;
if(snd->offset == snd->sound->sampleCount) {
*snd = sounds[activeSounds-1];
--activeSounds;
}
}
canmix = false;
}

11
src/mixer.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include <stdint.h>
#include "sound.h"
void mixer_init(void);
void mixer_deinit(void);
int16_t const* mixer_getNextBlock(void);
void mixer_play(sound_t const *sound);
void mixer_mix(void);

15
src/sound.c Normal file
View File

@@ -0,0 +1,15 @@
#include <stdint.h>
#include "sound.h"
#include "lib/dmt/dmt.h"
int sound_init(sound_t *self, int samples) {
self->sampleCount = samples;
self->samples = (int16_t*)dmt_malloc(samples * sizeof(int16_t));
return 0;
}
void sound_deinit(sound_t *self) {
dmt_free(self->samples);
}

14
src/sound.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef SOUND_H
#define SOUND_H
typedef struct {
int sampleCount;
int16_t *samples;
} sound_t;
int sound_init(sound_t *self, int samples);
void sound_deinit(sound_t *self);
#endif

View File

@@ -44,6 +44,8 @@ static uint16_t dmaChannel;
#define BLASTER_PROGRAM_STEREO 0x20
#define BLASTER_PROGRAM_SIGNED 0x10
#define BLASTER_SPEAKER_ON_CMD 0xD1
#define BLASTER_SPEAKER_OFF_CMD 0xD3
#define BLASTER_EXIT_AUTO_DMA 0xD9
// PIC
@@ -78,8 +80,10 @@ static const struct {
{ 0xC8, 0xCA, 0xD4, 0xD6, 0xD8, 0x89 },
{ 0xCC, 0xCE, 0xD4, 0xD6, 0xD8, 0x8A }
};
int stopDma = 0;
// ISR data
int isrInstalled = 0;
static _go32_dpmi_seginfo oldBlasterHandler, newBlasterHandler;
int writePage = 0;
@@ -87,14 +91,13 @@ static soundblaster_getSampleProc getSamples;
static void writeDSP(uint8_t value) {
while((inportb(baseAddress + BLASTER_WRITE_PORT) &
BLASTER_WRITE_BUFFER_STATUS_UNAVAIL) != 0)
;
BLASTER_WRITE_BUFFER_STATUS_UNAVAIL) != 0) {}
outportb(baseAddress + BLASTER_WRITE_PORT, value);
}
static int resetBlaster() {
static int resetBlaster(void) {
for(int j = 0; j < 1000; ++j) {
outportb(baseAddress + BLASTER_RESET_PORT, 1);
delay(1);
@@ -112,19 +115,24 @@ static int resetBlaster() {
}
static void soundblasterISR() {
outportb(baseAddress + BLASTER_MIXER_OUT_PORT,
BLASTER_MIXER_INTERRUPT_STATUS);
uint8_t status = inportb(baseAddress + BLASTER_MIXER_IN_PORT);
static void soundblasterISR(void) {
if(stopDma == 1) {
writeDSP(BLASTER_EXIT_AUTO_DMA);
stopDma = 2;
} else {
outportb(baseAddress + BLASTER_MIXER_OUT_PORT,
BLASTER_MIXER_INTERRUPT_STATUS);
uint8_t status = inportb(baseAddress + BLASTER_MIXER_IN_PORT);
if(status & BLASTER_16BIT_INTERRUPT) {
uint8_t* dst = (uint8_t*)(sampleBuffer)
+ writePage * SAMPLE_BUFFER_SIZE / 2;
if(status & BLASTER_16BIT_INTERRUPT) {
uint8_t* dst = (uint8_t*)(sampleBuffer)
+ writePage * SAMPLE_BUFFER_SIZE / 2;
memcpy(dst, getSamples(), SAMPLE_BUFFER_SIZE / 2);
memcpy(dst, getSamples(), SAMPLE_BUFFER_SIZE / 2);
writePage = 1 - writePage;
inportb(baseAddress + BLASTER_INTERRUPT_ACKNOWLEDGE_16BIT);
writePage = 1 - writePage;
inportb(baseAddress + BLASTER_INTERRUPT_ACKNOWLEDGE_16BIT);
}
}
if(irq >= 8) {
@@ -134,7 +142,7 @@ static void soundblasterISR() {
}
static void setBlasterISR() {
static void setBlasterISR(void) {
// Map IRQ to interrupt number on the CPU
uint16_t interruptVector = irq + irq + (irq < 8)
? PIC_IRQ07_MAP
@@ -156,6 +164,8 @@ static void setBlasterISR() {
uint8_t irqmask = inportb(PIC2_DATA);
outportb(PIC2_DATA, irqmask & ~(1<<(irq-8)));
}
isrInstalled = 1;
}
@@ -175,7 +185,7 @@ static int parseBlasterSettings(void) {
}
static int allocSampleBuffer() {
static int allocSampleBuffer(void) {
static int maxRetries = 10;
int selectors[maxRetries];
int current;
@@ -211,11 +221,16 @@ static int allocSampleBuffer() {
}
static void turnSpeakerOn() {
static void turnSpeakerOn(void) {
writeDSP(BLASTER_SPEAKER_ON_CMD);
}
static void turnSpeakerOff(void) {
writeDSP(BLASTER_SPEAKER_OFF_CMD);
}
static void dmaSetupTransfer(int channel,
uint8_t direction,
bool autoReload,
@@ -252,7 +267,7 @@ static void dmaSetupTransfer(int channel,
}
static void startDMAOutput() {
static void startDMAOutput(void) {
uint32_t offset = (uint32_t)sampleBuffer;
uint32_t samples = SAMPLE_BUFFER_SIZE / sizeof(int16_t);
@@ -302,6 +317,33 @@ int soundblaster_init(soundblaster_getSampleProc getsamplesproc) {
}
void soundblaster_deinit(void) {
static void deallocSampleBuffer(void) {
__dpmi_free_dos_memory(sampleBufferSelector);
}
static void resetBlasterISR(void) {
if(isrInstalled == 1) {
uint16_t interruptVector = irq + irq + (irq < 8)
? PIC_IRQ07_MAP
: PIC_IRQ8F_MAP;
_go32_dpmi_set_protected_mode_interrupt_vector(interruptVector, &oldBlasterHandler);
isrInstalled = 0;
}
}
static void stopDMAOutput(void) {
stopDma = 1;
while(stopDma == 1) {}
}
void soundblaster_deinit(void) {
turnSpeakerOff();
stopDMAOutput();
resetBlaster();
resetBlasterISR();
deallocSampleBuffer();
}