You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
4.9 KiB
228 lines
4.9 KiB
//
|
|
// BeOS code for amp-0.7.4, (C) 1997 Andy Lo A Foe
|
|
//
|
|
|
|
|
|
#include <MediaKit.h>
|
|
#include <KernelKit.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "transform.h"
|
|
#include "audioIO.h"
|
|
#include "audio.h"
|
|
|
|
// Define the streambuf size here. streambuf is used
|
|
// as a simple fit buffer.
|
|
|
|
#define STREAMBUF_SIZE (32*1152)
|
|
|
|
long bytes_in_streambuf;
|
|
|
|
// streambuf definition and base indicator
|
|
|
|
BSubscriber *the_sub;
|
|
BDACStream *the_stream;
|
|
|
|
sem_id ok_to_read;
|
|
sem_id ok_to_write;
|
|
|
|
|
|
char streambuf[STREAMBUF_SIZE];
|
|
char *readbase;
|
|
|
|
static int au_vol = 100;
|
|
|
|
// Define our own printout function since we are
|
|
// first writing in the streambuf (not needed, I think,
|
|
// but I don't know if the DACStream accepts a buffer
|
|
// size of 1152. Try it...
|
|
|
|
void printout(void)
|
|
{
|
|
if (A_WRITE_TO_FILE) {
|
|
#ifndef NO_BYTE_SWAPPING
|
|
int i,j;
|
|
short *ptr;
|
|
|
|
if (nch==2) {
|
|
ptr=(short*)stereo_samples;
|
|
i=j=32 * 18 * 2;
|
|
} else {
|
|
ptr=(short*)mono_samples;
|
|
i=j=32 * 18;
|
|
}
|
|
|
|
for (;i>=0;--i)
|
|
ptr[i] = ptr[i] << 8 | ptr[i] >> 8;
|
|
#endif
|
|
|
|
if (nch==2)
|
|
fwrite(stereo_samples,1,sizeof stereo_samples,out_file);
|
|
else
|
|
fwrite(mono_samples,1,sizeof mono_samples,out_file);
|
|
}
|
|
|
|
|
|
if (A_AUDIO_PLAY) {
|
|
static char au_buf[STREAMBUF_SIZE];
|
|
static int au_ptr =0, avail = 0;
|
|
static int num_smp;
|
|
static char *readbase = &au_buf[0];
|
|
|
|
// Write amount of samples to copy somewhere
|
|
num_smp = (nch == 2 ? sizeof stereo_samples : sizeof mono_samples);
|
|
|
|
// Copy samples in the fit buffer
|
|
memcpy(au_buf+au_ptr,(nch == 2 ? (char *)stereo_samples : (char *)mono_samples),
|
|
num_smp);
|
|
|
|
// Increase fit buffer pointer and available sample count
|
|
au_ptr+=num_smp;
|
|
avail+=num_smp;
|
|
|
|
if (avail >= 4096) { // Are there enough smps to feed the stream?
|
|
audioWrite((char*)readbase,4096); // Feed it!
|
|
readbase+=4096; // Increase readbase
|
|
avail-=4096; // Decrease avail smps count
|
|
if (au_ptr == STREAMBUF_SIZE) { // At end of fit buffer?
|
|
au_ptr=0; // Reset all pointers
|
|
readbase=&au_buf[0];
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Fake Buffer functions, just to keep the sources clean,
|
|
// buffer.c should not be included in the link process...
|
|
|
|
int AUDIO_BUFFER_SIZE;
|
|
|
|
int
|
|
audioBufferOpen(int frequency, int stereo, int volume)
|
|
{
|
|
audioOpen(frequency, stereo, volume);
|
|
}
|
|
|
|
|
|
inline void
|
|
audioBufferWrite(char *buf,int bytes)
|
|
{
|
|
audioWrite(buf, bytes);
|
|
}
|
|
|
|
|
|
void
|
|
audioBufferClose()
|
|
{
|
|
audioClose();
|
|
}
|
|
|
|
|
|
int audioRead(char *buffer, int count)
|
|
{
|
|
//printf("acquiring ok_to_read (%d bytes)\n", count);
|
|
if (acquire_sem(ok_to_read)==B_NO_ERROR) {
|
|
for (register int i=0; i < count;i++) {
|
|
*(buffer++)+=*(readbase++);
|
|
}
|
|
bytes_in_streambuf-=count;
|
|
|
|
if (bytes_in_streambuf <= 0) {
|
|
release_sem(ok_to_write);
|
|
bytes_in_streambuf = 0;
|
|
} else {
|
|
release_sem(ok_to_read);
|
|
}
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
|
|
bool stream_func(void *arg, char *buf, size_t count, void *header)
|
|
{
|
|
audioRead(buf, count);
|
|
return TRUE;
|
|
}
|
|
|
|
void audioOpen() {
|
|
readbase = &streambuf[0];
|
|
|
|
bytes_in_streambuf = 0;
|
|
|
|
the_sub = new BSubscriber("amp DAC writer");
|
|
the_stream = new BDACStream();
|
|
|
|
the_sub->Subscribe(the_stream);
|
|
|
|
the_stream->SetSamplingRate(frequency);
|
|
|
|
// Create semaphores
|
|
ok_to_read = create_sem(0, "read sem");
|
|
ok_to_write = create_sem(1, "write sem");
|
|
|
|
}
|
|
|
|
void audioInit(int sampleSize,int frequency, int stereo)
|
|
{
|
|
|
|
// Initialize the streambuf
|
|
bytes_in_streambuf = 0;
|
|
memset(&streambuf, 0, STREAMBUF_SIZE);
|
|
|
|
|
|
// Enter the stream
|
|
the_sub->EnterStream(NULL, TRUE, NULL, stream_func, NULL, TRUE);
|
|
}
|
|
|
|
|
|
void audioSetVolume(int volume)
|
|
{
|
|
if (volume > 128) // This allows for a modest volume boost
|
|
volume = 128;
|
|
au_vol = volume;
|
|
}
|
|
|
|
|
|
void audioClose()
|
|
{
|
|
the_sub->ExitStream(TRUE);
|
|
the_sub->Unsubscribe();
|
|
|
|
delete_sem(ok_to_read);
|
|
delete_sem(ok_to_write);
|
|
|
|
delete the_sub;
|
|
delete the_stream;
|
|
}
|
|
|
|
|
|
// audioWrite is called from the player thread
|
|
|
|
int audioWrite(char *buffer, int count)
|
|
{
|
|
//printf("acquiring ok_to_write (%d bytes)\n", count);
|
|
if(acquire_sem(ok_to_write)==B_NO_ERROR)
|
|
{
|
|
memcpy(&streambuf, buffer, count);
|
|
|
|
if (au_vol != 100) { // Handle volume scaling here
|
|
short *b=(short *)&streambuf;
|
|
for (int i=0; i < count/2; i++) {
|
|
int v=((int)b[i]*au_vol)/100;
|
|
b[i]=(v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
|
|
}
|
|
}
|
|
|
|
bytes_in_streambuf = count;
|
|
readbase = &streambuf[0];
|
|
|
|
release_sem(ok_to_read);
|
|
}
|
|
return 0;
|
|
}
|
|
|