Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Alcaro committed May 6, 2014
0 parents commit 2287521
Show file tree
Hide file tree
Showing 51 changed files with 24,111 additions and 0 deletions.
30 changes: 30 additions & 0 deletions COPYING
@@ -0,0 +1,30 @@

Redistribution and use of this code or any derivative works are permitted
provided that the following conditions are met:

* Redistributions may not be sold, nor may they be used in a commercial
product or activity.

* Redistributions that are modified from the original source must include the
complete source code, including the source code for all components used by a
binary built from the modified sources. However, as a special exception, the
source code distributed need not include anything that is normally distributed
(in either source or binary form) with the major components (compiler, kernel,
and so on) of the operating system on which the executable runs, unless that
component itself accompanies the executable.

* Redistributions must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
98 changes: 98 additions & 0 deletions Makefile
@@ -0,0 +1,98 @@
CC = gcc
CFLAGS = -g -Wall -Werror
LD = gcc
LFLAGS =

ifeq ($(platform),)
uname := $(shell uname -a)
ifeq ($(uname),)
platform := win
delete = del $(subst /,\,$1)
EXESUFFIX = .exe
else ifneq ($(findstring Darwin,$(uname)),)
platform := osx
delete = rm -f $1
EXESUFFIX =
else
platform := x
delete = rm -f $1
EXESUFFIX =
endif
endif

#TESTSRC = libretro.c rewind*.c inputraw-*keymaps.c dylib.c thread-*.c
TESTSRC =
TESTSEPSRC = window*.c test-*.c

OBJS = $(patsubst %.c,obj/%.o,$(wildcard *.c))
TESTOBJS = $(patsubst %.c,obj/%.o,$(wildcard $(TESTSRC))) $(patsubst %.c,obj/%-test.o,$(wildcard $(TESTSEPSRC)))

all: minir

#Rules for which dependencies are allowed:
#If there is no reasonable way to continue the program without this library, then make use of it.
#If a library matches the above rule, no effort needs to be spent on getting rid of it from other locations.
#If the library is only a link-time dependency and not needed at runtime, then it's fine.
#Otherwise, effort shall be spent on getting rid of this dependency. It's fine temporarily, but don't leave it there forever.
ifeq ($(platform),x)
TRUE_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags gtk+-3.0 libpulse) -pthread
TRUE_LFLAGS = $(LFLAGS) $(shell pkg-config --libs gtk+-3.0 libpulse) -pthread -ldl -lX11 -lGL -lXi -lXext -lpulse
#pthread - core (thread), links in threadsafe malloc
#gtk+-3.0 - core (window)
#libpulse - audio.pulseaudio - link only
#dl - core (dylib)
#X11 - core (libretro/hardware mapping), video.opengl, input.x11-xinput2? - FIXME
#GL - video.opengl - FIXME
#Xi - input.x11-xinput2 - FIXME
#Xext - video.xshm - FIXME
#pulse - audio.pulseaudio - FIXME
else ifeq ($(platform),osx)
#can't do this
else ifeq ($(platform),win)
TRUE_CFLAGS = $(CFLAGS) -Wno-format
TRUE_LFLAGS = $(LFLAGS) -lgdi32 -lcomctl32 -lcomdlg32 -ldinput8 -ldxguid -lopengl32 -ldsound
#gdi32 - core (window - fonts), video.gdi, video.opengl
#comctl32 - core (window - inner)
#comdlg32 - core (window - open file dialog)
#dinput8 - input.directinput - link only
#dxguid - audio.directsound, input.directinput - link only
#opengl32 - video.opengl - FIXME
#dsound - audio.directsound - FIXME
RESOBJ = obj/resource.o
OBJS += $(RESOBJ)
TESTOBJS += $(RESOBJ)
obj/resource.o: ico/*
windres ico/minir.rc obj/resource.o
else
$(error Unknown platform.)
endif

TRUE_CFLAGS += -std=gnu99
TRUE_LFLAGS +=


#$(CC) $(TRUE_CFLAGS) -DTEST -DNO_ICON test*.c window*.c $(TRUE_LFLAGS) -otest $(RESOBJ)
test: $(TESTOBJS)
$(LD) $+ $(TRUE_LFLAGS) -o $@

clean:
rm obj/* || true

obj:
mkdir obj

obj/config.o: config.c obj/config.c | obj
obj/main.o: main.c obj/config.c minir.h | obj
obj/%.o: %.c | obj obj/config.c
$(CC) $(TRUE_CFLAGS) -c $< -o $@

obj/%-test.o: %.c | obj obj/config.c
$(CC) $(TRUE_CFLAGS) -c $< -o $@ -DTEST -DNO_ICON

obj/config.c: obj/configgen$(EXESUFFIX) minir.cfg.tmpl
obj/configgen$(EXESUFFIX)
obj/configgen$(EXESUFFIX): configgen.c
$(CC) $(TRUE_CFLAGS) $(TRUE_LFLAGS) -DCONFIGGEN configgen.c -o obj/configgen$(EXESUFFIX)

minir: $(OBJS)
$(LD) $+ $(TRUE_LFLAGS) -o $@ -lm
177 changes: 177 additions & 0 deletions audio-directsound.c
@@ -0,0 +1,177 @@
#include "minir.h"
#ifdef AUDIO_DIRECTSOUND
#include <dsound.h>

//this file is heavily based on ruby by byuu

const GUID GUID_NULL={0};

struct audio_directsound {
struct audio i;

LPDIRECTSOUND ds;
LPDIRECTSOUNDBUFFER dsb_p;
LPDIRECTSOUNDBUFFER dsb_b;

DWORD lastwrite;

DWORD bufsize;

bool sync;
double samplerate;//only needed for changing latency, but they can be changed separately and in any order
};

static void createbuf(struct audio_directsound * this, double samplerate, double latency);

static void render(struct audio * this_, unsigned int numframes, const int16_t * samples)
{
struct audio_directsound * this=(struct audio_directsound*)this_;

DWORD freeend;
DWORD freestart;
DWORD thispos=this->lastwrite;

wait:
this->dsb_b->lpVtbl->GetCurrentPosition(this->dsb_b, &freeend, &freestart);
freestart/=4; freeend/=4;
if (thispos<freestart) thispos+=this->bufsize;
if (freeend<thispos) freeend+=this->bufsize;

if (thispos+numframes>freeend)
{
if (this->sync) { Sleep(1); goto wait; }
else numframes=freeend-thispos;
}

void* data1; DWORD data1bytes;
void* data2; DWORD data2bytes;
if (this->dsb_b->lpVtbl->Lock(this->dsb_b, thispos%this->bufsize*4, numframes*4, &data1, &data1bytes, &data2, &data2bytes, 0) == DS_OK)
{
memcpy(data1, samples, data1bytes);
memcpy(data2, samples+data1bytes/4*2, data2bytes);
this->dsb_b->lpVtbl->Unlock(this->dsb_b, data1, data1bytes, data2, data2bytes);
this->lastwrite=(thispos+(data1bytes+data2bytes)/4) % this->bufsize;
}
}

static void clear(struct audio * this_)
{
struct audio_directsound * this=(struct audio_directsound*)this_;

if (!this->dsb_b) return;
this->dsb_b->lpVtbl->Stop(this->dsb_b);
this->dsb_b->lpVtbl->SetCurrentPosition(this->dsb_b, 0);

DWORD size;
void* buffer;
this->dsb_b->lpVtbl->Lock(this->dsb_b, 0, -1, &buffer, &size, 0, 0, DSBLOCK_ENTIREBUFFER);
memset(buffer, 0, size);
this->dsb_b->lpVtbl->Unlock(this->dsb_b, buffer, size, 0, 0);

this->dsb_b->lpVtbl->Play(this->dsb_b, 0, 0, DSBPLAY_LOOPING);

this->lastwrite=0;
}

static void set_samplerate(struct audio * this_, double samplerate)
{
struct audio_directsound * this=(struct audio_directsound*)this_;
this->samplerate=samplerate;
this->dsb_b->lpVtbl->SetFrequency(this->dsb_b, samplerate);
}

static void set_latency(struct audio * this_, double latency)
{
struct audio_directsound * this=(struct audio_directsound*)this_;

if (this->dsb_b) this->dsb_b->lpVtbl->Release(this->dsb_b);

createbuf(this, this->samplerate, latency);
}

static void set_sync(struct audio * this_, bool sync)
{
struct audio_directsound * this=(struct audio_directsound*)this_;
this->sync=sync;
}

static bool has_sync(struct audio * this_)
{
return true;
}

static void free_(struct audio * this_)
{
struct audio_directsound * this=(struct audio_directsound*)this_;

if (this->dsb_b) { this->dsb_b->lpVtbl->Stop(this->dsb_b); this->dsb_b->lpVtbl->Release(this->dsb_b); }
if (this->dsb_p) { this->dsb_p->lpVtbl->Stop(this->dsb_p); this->dsb_p->lpVtbl->Release(this->dsb_p); }
if (this->ds) { this->ds->lpVtbl->Release(this->ds); }

free(this);
}

struct audio * audio_create_directsound(uintptr_t windowhandle, double samplerate, double latency)
{
struct audio_directsound * this=malloc(sizeof(struct audio_directsound));
this->i.render=render;
this->i.clear=clear;
this->i.set_samplerate=set_samplerate;
this->i.set_latency=set_latency;
this->i.set_sync=set_sync;
this->i.has_sync=has_sync;
this->i.free=free_;
this->sync=true;

this->samplerate=samplerate;

DirectSoundCreate(0, &this->ds, 0);
if (!this->ds)
{
free(this);
return NULL;
}
this->ds->lpVtbl->SetCooperativeLevel(this->ds, (HWND)windowhandle, DSSCL_PRIORITY);

this->bufsize=samplerate*latency/1000.0+0.5;

DSBUFFERDESC dsbd;
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = 0;
this->ds->lpVtbl->CreateSoundBuffer(this->ds, &dsbd, &this->dsb_p, 0);

createbuf(this, samplerate, latency);

return (struct audio*)this;
}

static void createbuf(struct audio_directsound * this, double samplerate, double latency)
{
this->bufsize=this->samplerate*latency/1000.0+0.5;

WAVEFORMATEX wfx;
memset(&wfx, 0, sizeof(wfx));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = this->samplerate;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;

DSBUFFERDESC dsbd;
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE;
dsbd.dwBufferBytes = this->bufsize * sizeof(uint32_t);
dsbd.guid3DAlgorithm = GUID_NULL;
dsbd.lpwfxFormat = &wfx;
this->ds->lpVtbl->CreateSoundBuffer(this->ds, &dsbd, &this->dsb_b, 0);
this->dsb_b->lpVtbl->SetFrequency(this->dsb_b, this->samplerate);
this->dsb_b->lpVtbl->SetCurrentPosition(this->dsb_b, 0);

clear((struct audio*)this);
}
#endif

0 comments on commit 2287521

Please sign in to comment.