Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

gp32std_sound.cpp

/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2006 The ScummVM project
 * Copyright (C) 2002 Ph0x - GP32 Backend
 * Copyright (C) 2003/2004 DJWillis - GP32 Backend
 * Copyright (C) 2005 Won Star - GP32 Backend
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-9-1/backends/gp32/gp32std_sound.cpp $
 * $Id: gp32std_sound.cpp 23341 2006-06-29 08:22:45Z wonst719 $
 *
 */

#include "stdafx.h"
#include "common/scummsys.h"

#include "gp32std.h"
#include "gp32std_sound.h"

#define GP32_TIMER_AUDIO_IDX 0

// Global variables
static volatile unsigned int frame = 0;
static volatile unsigned int *soundPos = 0;
static volatile int idx_buf;
static volatile unsigned int shiftVal = 0;
static void *buffer;
static GPSOUNDBUF soundBuf;

// This routine gets called by the timer interrupt and
// polls the current playing position within the buffer.

static void soundTimer() {
      static int locked = false;

      if (locked) {
            return;
      }

      locked = true;

      unsigned int sampleshiftVal = soundBuf.samples << shiftVal;
      unsigned int t = (((unsigned int)(*soundPos) - (unsigned int)buffer) >> shiftVal) >= soundBuf.samples ? 1 : 0;
      if (t != frame) {
            unsigned int offs = ((frame == 1) ? (sampleshiftVal) : 0);
            //memset((uint8 *)buffer + offs, 0, sampleshiftVal);
            soundBuf.callback(soundBuf.userdata, (uint8 *)((unsigned int)buffer + offs), sampleshiftVal);
            frame = t;
            {
                  // Play silence
                  register uint16 *d = (uint16 *)((uint8 *)buffer + offs); // alignment-safe
                  register uint32 max = (uint32)((uint8 *)buffer + offs + sampleshiftVal);
                  do {
                        *d++ ^= 0x8000; // 1
                        *d++ ^= 0x8000; // 2
                        *d++ ^= 0x8000; // 3
                        *d++ ^= 0x8000; // 4
                        *d++ ^= 0x8000; // 5
                        *d++ ^= 0x8000; // 6
                        *d++ ^= 0x8000; // 7
                        *d++ ^= 0x8000; // 8
                        *d++ ^= 0x8000; // 9
                        *d++ ^= 0x8000; // 10
                        *d++ ^= 0x8000; // 11
                        *d++ ^= 0x8000; // 12
                        *d++ ^= 0x8000; // 13
                        *d++ ^= 0x8000; // 14
                        *d++ ^= 0x8000; // 15
                        *d++ ^= 0x8000; // 16
                        *d++ ^= 0x8000; // 17
                        *d++ ^= 0x8000; // 18
                        *d++ ^= 0x8000; // 19
                        *d++ ^= 0x8000; // 20
                        *d++ ^= 0x8000; // 21
                        *d++ ^= 0x8000; // 22
                        *d++ ^= 0x8000; // 23
                        *d++ ^= 0x8000; // 24
                        *d++ ^= 0x8000; // 25
                        *d++ ^= 0x8000; // 26
                        *d++ ^= 0x8000; // 27
                        *d++ ^= 0x8000; // 28
                        *d++ ^= 0x8000; // 29
                        *d++ ^= 0x8000; // 30
                        *d++ ^= 0x8000; // 31
                        *d++ ^= 0x8000; // 32
                  } while ((uint32)d < max);
            }
      }

      locked = false;
}

int gp_soundBufStart(GPSOUNDBUF *sb) {
      int bufferSize = 0;

      PCM_SR gpFreq = PCM_S11;
      PCM_BIT gpFormat = PCM_16BIT;

      frame = 0;

      // Copy the structure
      memcpy(&soundBuf, sb, sizeof(GPSOUNDBUF));

      // Calculate size of a single sample in bytes
      // and a corresponding shift value
      shiftVal = 0;

      switch (soundBuf.format) {
      case 8:
            gpFormat = PCM_8BIT;
            break;
      case 16:
            gpFormat = PCM_16BIT;
            shiftVal++;
            break;
      }

      switch (soundBuf.freq) {
      case 11025:
            if (soundBuf.channels == 2) {
                  gpFreq = PCM_S11;
                  shiftVal++;
            } else
                  gpFreq = PCM_M11;
            break;
      case 22050:
            if (soundBuf.channels == 2) {
                  gpFreq = PCM_S22;
                  shiftVal++;
            } else
                  gpFreq = PCM_M22;
            break;
      case 44100:
            if (soundBuf.channels == 2) {
                  gpFreq = PCM_S44;
                  shiftVal++;
            } else
                  gpFreq = PCM_M44;
            break;
      }

      soundBuf.samplesize = 1 << shiftVal;
      
      // Allocate memory for the playing buffer
      bufferSize = soundBuf.samplesize * soundBuf.samples * 2;
      buffer = malloc(bufferSize);

      // Clear the buffer
      uint16 *tmpBuf = (uint16 *)buffer;
      for (int i = 0; i < bufferSize / 2; i++)
            tmpBuf[i] = 0x8000;

      // Frequency of the timer interrupt which polls the playing position
      // FIXME: This frequency should not be multiplied by 4.
      soundBuf.pollfreq = 4 * (2 * soundBuf.freq) / soundBuf.samples;

      // Set timer interrupt
      if (GpTimerOptSet(GP32_TIMER_AUDIO_IDX, soundBuf.pollfreq, 0, soundTimer) == GPOS_ERR_ALREADY_USED) {
            GPDEBUG(" Timer is already used... kill timer");
            GpTimerKill(GP32_TIMER_AUDIO_IDX);
      }
      GpTimerSet(GP32_TIMER_AUDIO_IDX);

      GpPcmInit(gpFreq, gpFormat);
      GpPcmPlay((unsigned short *)buffer, bufferSize, 1);
      GpPcmLock((unsigned short *)buffer, (int *)&idx_buf, (unsigned int *)&soundPos);

      return 0;
}

void gp_soundBufStop() {
      GpTimerKill(GP32_TIMER_AUDIO_IDX);
      GpPcmStop();
      GpPcmRemove((unsigned short *)buffer);
      free(buffer);
}

Generated by  Doxygen 1.6.0   Back to index