#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include "ao.h"
#include "oss.h"
#define LOG_WAVE (0)
#define VALGRIND (0)
#define NUM_FRAGS_BROKEN (8)
#define NUM_FRAGS_NORMAL (4)
static INT32 num_frags;
#define OSS_FRAGMENT (0x000D | (num_frags<<16));
void (*m1sdr_Callback)(unsigned long dwNumSamples, signed short *data);
unsigned long cbUserData;
static int hw_present;
static INT32 is_broken_driver;
int nDSoundSegLen = 0;
int oss_nw = 0;
int audiofd;
#if LOG_WAVE
FILE *logfil;
#endif
static int playtime = 0;
static INT16 samples[44100*2];
void m1sdr_SetSamplesPerTick(UINT32 spf)
{
nDSoundSegLen = spf;
}
void m1sdr_Update(void)
{
if (!hw_present) return;
if (m1sdr_Callback)
{
m1sdr_Callback(nDSoundSegLen, (INT16 *)samples);
}
}
void m1sdr_TimeCheck(void)
{
#if VALGRIND
m1sdr_Update();
#else
audio_buf_info info;
ioctl(audiofd, SNDCTL_DSP_GETOSPACE, &info);
if (oss_nw)
{
int err;
m1sdr_Update();
playtime++;
err = write(audiofd, samples, nDSoundSegLen * 4);
if (err == -1)
{
perror("write\n");
}
#if LOG_WAVE
fwrite(samples, nDSoundSegLen*4, 1, logfil);
#endif
}
else
{
while (info.bytes >= (nDSoundSegLen * 4))
{
m1sdr_Update();
playtime++;
write(audiofd, samples, nDSoundSegLen * 4);
#if LOG_WAVE
fwrite(samples, nDSoundSegLen*4, 1, logfil);
#endif
ioctl(audiofd, SNDCTL_DSP_GETOSPACE, &info);
}
}
usleep(50);
#endif
}
INT16 m1sdr_Init(int sample_rate)
{
int format, stereo, rate, fsize;
hw_present = 0;
nDSoundSegLen = sample_rate / 60;
memset(samples, 0, 44100*4);
m1sdr_Callback = NULL;
audiofd = open("/dev/dsp", O_WRONLY, 0);
if (audiofd == -1)
{
perror("/dev/dsp");
audiofd = open("/dev/dsp1", O_WRONLY, 0);
if (audiofd == -1)
{
perror("/dev/dsp1");
return(0);
}
}
ioctl(audiofd, SNDCTL_DSP_RESET, 0);
is_broken_driver = 0;
num_frags = NUM_FRAGS_NORMAL;
fsize = OSS_FRAGMENT;
if (ioctl(audiofd, SNDCTL_DSP_SETFRAGMENT, &fsize) == - 1)
{
perror("SNDCTL_DSP_SETFRAGMENT");
return(0);
}
format = AFMT_S16_NE; if (ioctl(audiofd, SNDCTL_DSP_SETFMT, &format) == - 1)
{
perror("SNDCTL_DSP_SETFMT");
return(0);
}
stereo = 1;
if (ioctl(audiofd, SNDCTL_DSP_STEREO, &stereo) == - 1)
{
perror("SNDCTL_DSP_STEREO");
return(0);
}
rate = sample_rate;
if (ioctl(audiofd, SNDCTL_DSP_SPEED, &rate) == - 1)
{
perror("SNDCTL_DSP_SPEED");
return(0);
}
ioctl(audiofd, SNDCTL_DSP_GETBLKSIZE, &fsize);
hw_present = 1;
#if LOG_WAVE
logfil = fopen("log.bin", "wb");
#endif
return (1);
}
void m1sdr_Exit(void)
{
if (!hw_present) return;
close(audiofd);
#if LOG_WAVE
fclose(logfil);
#endif
}
void m1sdr_SetCallback(void *fn)
{
if (fn == (void *)NULL)
{
printf("ERROR: NULL CALLBACK!\n");
}
m1sdr_Callback = (void (*)(unsigned long, signed short *))fn;
}
INT16 m1sdr_IsThere(void)
{
audiofd = open("/dev/dsp", O_WRONLY, 0);
if (audiofd == -1)
{
printf("Error accessing soundcard, sound will be disabled\n");
hw_present = 0;
return(0);
}
close(audiofd);
hw_present = 1;
return (1);
}
INT32 m1sdr_HwPresent(void)
{
return hw_present;
}
void m1sdr_PlayStart(void)
{
playtime = 0;
}
void m1sdr_PlayStop(void)
{
}
void m1sdr_FlushAudio(void)
{
memset(samples, 0, nDSoundSegLen * 4);
write(audiofd, samples, nDSoundSegLen * 4);
write(audiofd, samples, nDSoundSegLen * 4);
}
void m1sdr_SetNoWait(int nw)
{
oss_nw = nw;
}
short *m1sdr_GetSamples(void)
{
return samples;
}
int m1sdr_GetPlayTime(void)
{
return playtime;
}