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

sound.h

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-2-0/engines/draci/sound.h $
 * $Id: sound.h 50618 2010-07-03 05:05:28Z spalek $
 *
 */

#ifndef DRACI_SOUND_H
#define DRACI_SOUND_H

#include "common/str.h"
#include "common/file.h"
#include "common/list.h"
#include "sound/mixer.h"

namespace Common {
class Archive;
class SeekableReadStream;
}

namespace Draci {

enum SoundFormat { RAW, RAW80, MP3, OGG, FLAC };      // RAW80 means skip the first 80 bytes

/**
 *  Represents individual files inside the archive.
 */
00046 struct SoundSample {
      uint _offset;           // For internal use of LegacySoundArchive
      uint _length;

      uint _frequency;  // Only when _format == RAW or RAW80
      SoundFormat _format;

      byte *_data;            // At most one of these two pointer can be non-NULL
      Common::SeekableReadStream* _stream;

      SoundSample() : _offset(0), _length(0), _frequency(0), _format(RAW), _data(NULL), _stream(NULL) { }
      // The standard copy constructor is good enough, since we only store numbers and pointers.
      // Don't call close() automaticall in the destructor, otherwise copying causes SIGSEGV.
      void close() {
            delete[] _data;
            delete _stream;
            _data = NULL;
            _stream = NULL;
      }
};

/**
 * An abstract wrapper around archives of sound samples or dubbing.
 */
00070 class SoundArchive {
public:
      SoundArchive() { }
      virtual ~SoundArchive() { }

      /**
       * Returns the number of sound samples in the archive.  Zero means that
       * a fake empty archive has been opened and the caller may consider
       * opening a different one, for example with compressed music.
       */
      virtual uint size() const = 0;

      /**
       * Checks whether there is an archive opened. Should be called before reading
       * from the archive to check whether opening of the archive has succeeded.
       */
      virtual bool isOpen() const = 0;

      /**
       * Removes cached samples from memory.
       */
      virtual void clearCache() = 0;

      /**
       * Caches a given sample into memory and returns a pointer into it.  We
       * own the returned pointer, but the user may call .close() on it,
       * which deallocates the memory of the actual sample data.  If freq is
       * nonzero, then the sample is played at a different frequency (only
       * works for uncompressed samples).
       */
      virtual SoundSample *getSample(int i, uint freq) = 0;
};

/**
 * Reads CD.SAM (with dubbing) and CD2.SAM (with sound samples) from the
 * original game.  Caches all read samples in a thread-safe manner.
 */
00107 class LegacySoundArchive : public SoundArchive {
public:
      LegacySoundArchive(const char *path, uint defaultFreq) :
      _path(NULL), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) {
            openArchive(path);
      }
      virtual ~LegacySoundArchive() { closeArchive(); }

      void openArchive(const char *path);
      void closeArchive();

00118       virtual uint size() const { return _sampleCount; }
00119       virtual bool isOpen() const { return _opened; }

      virtual void clearCache();
      virtual SoundSample *getSample(int i, uint freq);

private:
00125       const char *_path;    ///< Path to file
00126       SoundSample *_samples;          ///< Internal array of files
00127       uint _sampleCount;         ///< Number of files in archive
00128       uint _defaultFreq;      ///< The default sampling frequency of the archived samples
00129       bool _opened;            ///< True if the archive is opened, false otherwise
00130       Common::File *_f; ///< Opened file
};

/**
 * Reads ZIP archives with uncompressed files containing lossy-compressed
 * samples in arbitrary format.  Doesn't do any real caching and is
 * thread-safe.
 */
00138 class ZipSoundArchive : public SoundArchive {
public:
      ZipSoundArchive() : _archive(NULL), _path(NULL), _extension(NULL), _format(RAW), _sampleCount(0), _defaultFreq(0), _cache() { }
      virtual ~ZipSoundArchive() { closeArchive(); }

      void openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency = 0);
      void closeArchive();

00146       virtual uint size() const { return _sampleCount; }
00147       virtual bool isOpen() const { return _archive != NULL; }

      virtual void clearCache();
      virtual SoundSample *getSample(int i, uint freq);

private:
      Common::Archive *_archive;
      const char *_path;
      const char *_extension;
      SoundFormat _format;
      uint _sampleCount;
      uint _defaultFreq;

      // Since we typically play at most 1 dubbing at a time, we could get
      // away with having just 1 record allocated and reusing it each time.
      // However, that would be thread-unsafe if two samples were played.
      // Although the player does not do that, it is nicer to allow for it in
      // principle.  For each dubbed sentence, we allocate a new record in
      // the following link-list, which is cleared during each location
      // change.  The dubbed samples themselves are manually deallocated
      // after they end.
      Common::List<SoundSample> _cache;
};

#define SOUND_HANDLES 10

enum sndHandleType {
      kFreeHandle,
      kEffectHandle,
      kVoiceHandle
};

struct SndHandle {
      Audio::SoundHandle handle;
      sndHandleType type;
};

// Taken from engines/saga/sound.h and simplified (in particular, removed
// decompression until we support compressed files too).
class Sound {
public:

      Sound(Audio::Mixer *mixer);
      ~Sound() {}

      uint playSound(const SoundSample *buffer, int volume, bool loop);
      void pauseSound();
      void resumeSound();
      void stopSound();
      bool isMutedSound() const { return _muteSound; }

      uint playVoice(const SoundSample *buffer);
      void pauseVoice();
      void resumeVoice();
      void stopVoice();
      bool isMutedVoice() const { return _muteVoice; }

      void stopAll() { stopVoice(); stopSound(); }

      void setVolume();

      bool showSubtitles() const { return _showSubtitles; }
      int talkSpeed() const { return _talkSpeed; }

 private:
      // Returns the length of the sound sample in miliseconds.
      uint playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume,
                        sndHandleType handleType, bool loop);

      SndHandle *getHandle();

      Audio::Mixer *_mixer;

      bool _muteSound;
      bool _muteVoice;
      bool _showSubtitles;
      int _talkSpeed;

      SndHandle _handles[SOUND_HANDLES];
};

} // End of namespace Draci

#endif // DRACI_SOUND_H

Generated by  Doxygen 1.6.0   Back to index