Priest of the Order of the Butterfly
Posts: 559 from 2012/6/8
From: Hungary
I'm not dead yet, it's just that the uade2 ANR player eats up all the free time I can dedicate to MorphOS. After some false starts I finally have a clear idea on how to get things together, but I have some questions.
Are there any good info on making shared libraries out there? Can I compile them with GCC4? Do I have to use some specific compiler/linker flags? I tried looking some makefiles, but they are all over the place. Also are there any restriction on using LibNIX functions?
The other thing is AHI double buffering. I made an AHI backend for uade123, and it sometimes hangs at the beginning of the playback. This is how the source looks like:
Code:
#include <stdlib.h>
#include <devices/ahi.h>
#include <proto/exec.h>
#ifndef __MORPHOS__
#define AllocTaskPooled(size) AllocMem(size, MEMF_ANY)
#define FreeTaskPooled(mem, size) FreeMem(mem, size)
#endif
#include "uadeconstants.h"
#include "audio.h"
#include "uade123.h"
/* this is hardcoded baby! */
#if (UADE_BYTES_PER_SAMPLE == 1)
#if (UADE_CHANNELS == 1)
#define type AHIST_M8S
#elif (UADE_CHANNELS == 2)
#define type AHIST_S8S
#else
#error Invalid channel number.
#endif
#elif (UADE_BYTES_PER_SAMPLE == 2)
#if (UADE_CHANNELS == 1)
#define type AHIST_M16S
#elif (UADE_CHANNELS == 2)
#define type AHIST_S16S
#else
#error Invalid channel number.
#endif
#else
#error Invalid bytes per sample value.
#endif
#define BUFSIZE (8192 * UADE_BYTES_PER_SAMPLE * UADE_CHANNELS)
static char AHIBuf[2][BUFSIZE];
static ULONG rate;
static struct MsgPort *AHIPort = NULL;
static struct AHIRequest *AHIReq[2] = { NULL, NULL };
static int active = 0;
static int slots = 2;
void audio_close (void)
{
if (AHIReq[1])
{
if (!CheckIO((struct IORequest *) AHIReq[1]))
{
AbortIO((struct IORequest *) AHIReq[1]);
WaitIO((struct IORequest *) AHIReq[1]);
}
FreeTaskPooled(AHIReq[1], sizeof(struct AHIRequest));
AHIReq[1] = NULL;
}
if (AHIReq[0])
{
if (!CheckIO((struct IORequest *) AHIReq[0]))
{
AbortIO((struct IORequest *) AHIReq[0]);
WaitIO((struct IORequest *) AHIReq[0]);
}
if (AHIReq[0]->ahir_Std.io_Device)
{
CloseDevice((struct IORequest *) AHIReq[0]);
AHIReq[0]->ahir_Std.io_Device = NULL;
}
DeleteIORequest((struct IORequest *) AHIReq[0]);
AHIReq[0] = NULL;
}
if (AHIPort)
{
DeleteMsgPort(AHIPort);
AHIPort = NULL;
}
}
int audio_init(const struct uade_config *uc)
{
if (uade_no_audio_output)
return 1;
rate = uc->frequency;
if ((AHIPort = CreateMsgPort()))
{
if ((AHIReq[0] = (struct AHIRequest *) CreateIORequest(AHIPort, sizeof(struct AHIRequest))))
{
AHIReq[0]->ahir_Version = 4;
if ((AHIReq[1] = (struct AHIRequest *) AllocTaskPooled(sizeof(struct AHIRequest))))
{
if (!OpenDevice("ahi.device", AHI_DEFAULT_UNIT, (struct IORequest *)AHIReq[0], 0))
{
AHIReq[0]->ahir_Std.io_Command = CMD_WRITE;
AHIReq[0]->ahir_Std.io_Offset = 0;
AHIReq[0]->ahir_Type = type;
AHIReq[0]->ahir_Frequency = rate;
AHIReq[0]->ahir_Volume = 0x10000;
AHIReq[0]->ahir_Position = 0x8000;
CopyMemQuick(AHIReq[0], AHIReq[1], sizeof(struct AHIRequest));
return 1;
}
FreeTaskPooled(AHIReq[1], sizeof(struct AHIRequest));
}
DeleteIORequest((struct IORequest *) AHIReq[0]);
}
DeleteMsgPort(AHIPort);
}
return 0;
}
int audio_play(unsigned char* output_samples, int num_bytes)
{
int size;
if (uade_no_audio_output)
return 1;
while (num_bytes)
{
WaitIO((struct IORequest *) AHIReq[active]);
size = (BUFSIZE > num_bytes) ? num_bytes : BUFSIZE;
CopyMem(output_samples, AHIBuf[active], num_bytes);
num_bytes -= size;
AHIReq[active]->ahir_Std.io_Data = AHIBuf[active];
AHIReq[active]->ahir_Std.io_Length = size;
AHIReq[active]->ahir_Link = AHIReq[active ^ 1];
SendIO((struct IORequest *) AHIReq[active]);
// swap buffers
active ^= 1;
}
return 1;
}
are there any obvious problems there?
This is just like television, only you can see much further.