(sorry, posted this with the wrong from address previously)

I'm taking another look at adding sound support to the Amiga version.

The X sound.c opens and writes to /dev/dsp. I've changed these calls
to use the Amiga/AHI AUDIO: device which - as far as I can tell -
works in the same way.  I have pthreads, so with some other minor
modifications (mostly the removal of the ioctl calls, which I don't
need), sound support compiles in without complaining.

However, after about one flash of the RISC OS cursor, the emulator
appears to freeze.  It appears to still be running as everything else
slows down as if CPU time is being used.

If I comment out this part of sound_poll, I get sound (of sorts, it
just plays the garbage that was in the buffer when it was first
allocated):

      if (SoundDMAFetch(buffer + localBufferWrite) == 1) {
        return;
      }

What values does SoundDMAFetch return, and does anybody have any ideas
why the code as above (which presumably works OK in the X version) is
causing the emulation to hang here?

On a related note, why is there no sound_exit function?  It opens the
audio stream, allocates a buffer, but there is no deallocation that I
can see?  Surely we should have some form of sound clean-up function
in sound.c?

Thanks
Chris

#include "platform.h"

#include <stdio.h>
#include <stdlib.h>

#include "pthread.h"

#include "../armdefs.h"
#include "../arch/sound.h"

BPTR audioh = 0;

//static unsigned long format = AFMT_S16_LE;
static unsigned long channels = 2;
/*static unsigned long bits = 16;*/
static unsigned long sampleRate = 0;

static unsigned long bufferSize = 0;

/*static unsigned long numberGot = 0;*/

static unsigned long bufferRead = 0;
static unsigned long bufferWrite = 0;

/* This is how many 16 byte blocks to get before leaving
 * sound_poll to return to the emulator */
static unsigned long blocksAtATime = 1;
/* This is how many 16 byte blocks should be collected before
 * calling write(), so this controls the size of the buffer. */
static unsigned long numberOfFills = 100;

/* This is the size of the gap between sound_poll doing something. */
static unsigned long delayTotal = 100;
static unsigned long delayProgress = 0;

//static int soundDevice;
static APTR buffer = NULL;

static pthread_t thread;
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;


void
sound_poll(void)
{
  static unsigned long localBufferWrite = 0;

delayProgress++;
  if (delayProgress >= delayTotal) {
    int i;

    /*bufferWrite = (numberGot + i) * 16 * 2);*/

    for (i = 0; i < blocksAtATime; i++) {
      /* *Important*, you must respect whether sound dma
       * is enabled or not at all times otherwise sound
       * will come out wrong.
       */
      /*if( SoundDMAFetch(buffer + ((numberGot + i) * 16 * 2)) == 1 ) return; */
/*
      if (SoundDMAFetch(buffer + localBufferWrite) == 1) {
        return;
      }
*/
    }

    localBufferWrite += (blocksAtATime * 16 * 2);
    if (localBufferWrite >= (bufferSize / 16)) {
      localBufferWrite = 0;
    }

    if (pthread_mutex_trylock(&mut) == 0) {
      bufferWrite = localBufferWrite;

      pthread_mutex_unlock(&mut);
      pthread_cond_broadcast(&cond);
    } 

    delayProgress = 0;
  }
}

static void *
sound_writeThread(void *arg)
{
        printf("audio: sound_writethread\n");
  for (;;) {
    int y;
        printf("audio: ^^\n");

    pthread_mutex_lock(&mut); //
    y = bufferWrite;
    pthread_mutex_unlock(&mut);

    if (bufferRead != y) {
      if (y < bufferRead) {
        y = bufferSize / 16;
      }

        IDOS->Write(audioh,buffer+bufferRead,(y-bufferRead)*16);

/*
      write(soundDevice, buffer + bufferRead,
            (y - bufferRead) * 16);
*/

      bufferRead = y;
      if (bufferRead >= (bufferSize / 16)) {
        bufferRead = 0;
      }
    }

else {
      pthread_mutex_lock(&mut); //
      pthread_cond_wait(&cond, &mut);
      pthread_mutex_unlock(&mut);
    }

  }

  return NULL;
}

int
sound_init(void)
{
        printf("audio: sound_init\n");

        if(!(audioh = 
IDOS->Open("AUDIO:BITS/16/C/2/F/44100/T/SIGNED",MODE_NEWFILE)))
        {
        fprintf(stderr, "Could not open audio: device\n");
        return -1;
        }

/*
  if ((soundDevice = open("/dev/dsp", O_CREAT | O_WRONLY )) < 0) {
    fprintf(stderr, "Could not open audio device /dev/dsp\n");
    return -1;
  }

  if (ioctl(soundDevice, SOUND_PCM_RESET, 0) == -1) {
    fprintf(stderr, "Could not reset PCM\n");
    return -1;
  }

  if (ioctl(soundDevice, SOUND_PCM_SYNC, 0) == -1) {
    fprintf(stderr, "Could not sync PCM\n");
    return -1;
  }

  if (ioctl(soundDevice, SOUND_PCM_SETFMT, &format) == -1) {
    fprintf(stderr, "Could not set PCM format\n");
    return -1;
  }

  if (ioctl(soundDevice, SOUND_PCM_WRITE_CHANNELS, &channels) == -1) {
    fprintf(stderr,"Could not set to 2 channel stereo\n");
    return -1;
  }

  if (ioctl(soundDevice, SOUND_PCM_WRITE_RATE, &sampleRate) == -1) {
    fprintf(stderr, "Could not set initial sample rate\n");
    return -1;
  }
*/

  bufferSize = numberOfFills * 16 * 2 * 16;

//printf("%ld\n",bufferSize);

  buffer = IExec->AllocVec(bufferSize,MEMF_CLEAR);
  if (!buffer) {
    fprintf(stderr, "sound_init(): Out of memory\n");
    exit(EXIT_FAILURE);
  }

  pthread_create(&thread, NULL, sound_writeThread, 0);

  return 0;
}

/**
 * sound_setSampleRate
 *
 * Set the sample rate of sound, using
 * the period specified in microseconds.
 *
 * @param period period of sample in microseconds
 */
void
sound_setSampleRate(unsigned long period)
{
  /* freq = 1 / (period * 10^-6) */
  if (period != 0) {
    sampleRate = 1000000 / period;
  } else {
    sampleRate = 44100;
  }

  printf("asked to set sample rate to %lu\n", sampleRate);
//  ioctl(soundDevice, SOUND_PCM_WRITE_RATE, &sampleRate);
//  ioctl(soundDevice, SOUND_PCM_READ_RATE, &sampleRate);
  printf("set sample rate to %lu\n", sampleRate);
}

void sound_exit(void)
{
        IExec->FreeVec(buffer);
        IDOS->Close(audioh);    
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
arcem-devel mailing list
arcem-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/arcem-devel

Reply via email to