#pragma once #ifndef TSOUND_INCLUDED #define TSOUND_INCLUDED #include #include "tsmartpointer.h" #include "texception.h" #include "tthreadmessage.h" #undef DVAPI #undef DVVAR #ifdef TSOUND_EXPORTS #define DVAPI DV_EXPORT_API #define DVVAR DV_EXPORT_VAR #else #define DVAPI DV_IMPORT_API #define DVVAR DV_IMPORT_VAR #endif #ifndef _WIN32 #define WAVE_FORMAT_PCM 1 #endif //========================================================= namespace TSound { typedef UCHAR Channel; const int MONO = 0; const int LEFT = 0; const int RIGHT = LEFT + 1; } //========================================================= // forward declarations class TSoundTrack; class TSoundTransform; #ifdef _WIN32 template class DVAPI TSmartPointerT; #endif typedef TSmartPointerT TSoundTrackP; //============================================================================== /*! The class TSoundTrackFormat contains the main features of a TSoundTrack as: sample rate, bit per sample, number of channels and signed or unsigned sample */ class DVAPI TSoundTrackFormat { public: TUINT32 m_sampleRate; // frequenza di campionamento int m_bitPerSample; // numero di bit per campione int m_channelCount; // numero di canali bool m_signedSample; int m_formatType; TSoundTrackFormat(TUINT32 sampleRate = 0, int bitPerSample = 0, int channelCount = 0, bool signedSample = true, int formatType = WAVE_FORMAT_PCM) : m_sampleRate(sampleRate) , m_bitPerSample(bitPerSample) , m_channelCount(channelCount) , m_signedSample(signedSample) , m_formatType(formatType) {} ~TSoundTrackFormat() {} bool operator==(const TSoundTrackFormat &rhs); bool operator!=(const TSoundTrackFormat &rhs); }; //============================================================================== //! \include sound_ex.cpp /*! The class TSoundTrack contains all features about a sound track and gives all methods to access to these informations */ class DVAPI TSoundTrack : public TSmartObject { DECLARE_CLASS_CODE protected: TUINT32 m_sampleRate; // frequenza di campionamento int m_sampleSize; // numero di byte per campione int m_bitPerSample; // numero di bit per campione TINT32 m_sampleCount; // numero di campioni int m_channelCount; // numero di canali int m_formatType; TSoundTrack *m_parent; // nel caso di sotto-traccie UCHAR *m_buffer; bool m_bufferOwner; TSoundTrack(); TSoundTrack(TUINT32 sampleRate, int bitPerSample, int channelCount, int sampleSize, TINT32 sampleCount, bool isSampleSigned, int formatType); TSoundTrack(TUINT32 sampleRate, int bitPerSample, int channelCount, int sampleSize, TINT32 sampleCount, UCHAR *buffer, TSoundTrack *parent, int formatType); public: /*! Create a new soundtrack according to the sample rate, bits per sample, number of channels and number of samples specified as inputs. signedSample must be true for tracks whose samples are signed */ static TSoundTrackP create(TUINT32 sampleRate, int bitPerSample, int channelCount, TINT32 sampleCount, bool signedSample = true, int formatType = WAVE_FORMAT_PCM); static TSoundTrackP create(TUINT32 sampleRate, int bitPerSample, int channelCount, TINT32 sampleCount, void *buffer, bool signedSample = true, int formatType = WAVE_FORMAT_PCM); /*! Create a new soundtrack according to the format and number of samples specified as inputs */ static TSoundTrackP create(const TSoundTrackFormat &format, TINT32 sampleCount); static TSoundTrackP create(const TSoundTrackFormat &format, TINT32 sampleCount, void *buffer); ~TSoundTrack(); //! Converts from seconds to samples according to the soundtrack sample rate TINT32 secondsToSamples(double sec) const; //! Converts from samples to seconds according to the soundtrack sample rate double samplesToSeconds(TINT32 smp) const; TUINT32 getSampleRate() const { return m_sampleRate; } int getSampleSize() const { return m_sampleSize; } int getChannelCount() const { return m_channelCount; } int getBitPerSample() const { return m_bitPerSample; } TINT32 getSampleCount() const { return m_sampleCount; } int getFormatType() const { return m_formatType; } //! Returns the duration of the soundtrack in seconds. double getDuration() const; //! Returns true if the samples of the soundtrack are signed, false otherwise virtual bool isSampleSigned() const = 0; //! Returns the soundtrack format TSoundTrackFormat getFormat() const; //! Returns a pointer to the samples buffer. const UCHAR *getRawData() const { return m_buffer; }; void setSampleRate(TUINT32 sampleRate) { m_sampleRate = sampleRate; } //! Clones the soundtrack virtual TSoundTrackP clone() const = 0; //! Returns a soundtrack that contains just the cloned channel virtual TSoundTrackP clone(TSound::Channel chan) const = 0; //! Returns a subtrack for the range [s0, s1], s0 and s1 are samples virtual TSoundTrackP extract(TINT32 s0, TINT32 s1) = 0; //! Returns a subtrack for the range [t0, t1], t0 and t1 are seconds TSoundTrackP extract(double t0, double t1); /*! Copies the all samples of the source soundtrack to the object, starting from dst_s0. dst_s0 is expressed in samples. */ virtual void copy(const TSoundTrackP &src, TINT32 dst_s0) = 0; /*! Copies the all samples of the source soundtrack to the object, starting from dst_t0. dst_t0 is expressed in seconds. */ void copy(const TSoundTrackP &src, double dst_t0); //! Blanks the soundtrack in the given range virtual void blank(TINT32 s0, TINT32 s1) = 0; /*! Blanks the soundtrack in the given range. Range is expressed in seconds. */ void blank(double t0, double t1); /*! Returns a new soundtrack obtained applying the given sound tranform to the soundtrack */ virtual TSoundTrackP apply(TSoundTransform *) = 0; //! Returns the soundtrack pressure value for the given sample and channel: //! range [-1,1] virtual double getPressure(TINT32 sample, TSound::Channel chan) const = 0; //! Returns the soundtrack pressure value for the given time and channel double getPressure(double second, TSound::Channel chan) const; //! Returns the soundtrack pressure max and min values in the given sample //! range and channel virtual void getMinMaxPressure(TINT32 s0, TINT32 s1, TSound::Channel chan, double &min, double &max) const = 0; /*! Returns the soundtrack pressure min and max values in the given range and channel. Range in seconds */ void getMinMaxPressure(double t0, double t1, TSound::Channel chan, double &min, double &max) const; //! Returns the soundtrack pressure min and max values for the given channel void getMinMaxPressure(TSound::Channel chan, double &min, double &max) const; //! Returns the soundtrack pressure max value in the given sample range and //! channel virtual double getMaxPressure(TINT32 s0, TINT32 s1, TSound::Channel chan) const = 0; /*! Returns the soundtrack pressure min value in the given range and channel. Range in seconds */ double getMaxPressure(double t0, double t1, TSound::Channel chan) const; //! Returns the soundtrack pressure max value for the given channel double getMaxPressure(TSound::Channel chan) const; //! Returns the soundtrack pressure max value in the given sample range and //! channel virtual double getMinPressure(TINT32 s0, TINT32 s1, TSound::Channel chan) const = 0; /*! Returns the soundtrack pressure mix value in the given sample range and channel Range in seconds */ double getMinPressure(double t0, double t1, TSound::Channel chan) const; //! Returns the soundtrack pressure min value for the given channel double getMinPressure(TSound::Channel chan) const; }; //============================================================================== class TSoundDeviceException final : public TException { public: enum Type { NoDevice, // no device found FailedInit, // fallimento del costruttore UnableOpenDevice, UnableCloseDevice, UnablePrepare, // non puo' preparare i blocchi per play o rec UnsupportedFormat, // formato non supportato UnableSetDevice, // non puo' impostare il device richiesto UnableVolume, // non puo' leggere o scrivere il valore del volume NoMixer, // assenza del dispositivo per regolare il volume Busy // indica che il dispositivo gia' sta facendo // un play od una registrazione }; TSoundDeviceException(Type type, const std::string &msg) : TException(msg), m_type(type) {} TSoundDeviceException(Type type, const std::wstring &msg) : TException(msg), m_type(type) {} Type getType() { return m_type; } private: Type m_type; }; //============================================================================== // forward declaration class TSoundInputDeviceImp; //! \include sndInDev_ex.cpp /*! The class TSoundInputDevice permits the recording of a new sound track */ class DVAPI TSoundInputDevice { std::shared_ptr m_imp; public: enum Source { Mic = 0, LineIn, DigitalIn, CdAudio }; TSoundInputDevice(); ~TSoundInputDevice(); /*! Returns true if on the machine there is an audio card installed correctly */ static bool installed(); //! Returns the best format supported near the given parameters TSoundTrackFormat getPreferredFormat(TUINT32 sampleRate, int channelCount, int bitPerSample, int formatType); //! Returns the best format supported near the given format TSoundTrackFormat getPreferredFormat(const TSoundTrackFormat &); //! Returns true if is possible to change volume setting on current input //! interface bool supportsVolume(); //! Starts the recording of a soundtrack with the given format from the given //! source. void record(const TSoundTrackFormat &format, Source devtype = Mic); /*! Starts the recording over the soundtrack st from the given source. If not stopped before, recording ends when the whole soundtrack has been overwritten. */ void record(const TSoundTrackP &st, Source src = Mic); //! Stops the recording and returns the result of recording. TSoundTrackP stop(); //! Return the current value of the volume double getVolume(); //! Set the value of the volume bool setVolume(double value); //! Returns true if and only if the device is recording bool isRecording(); }; //============================================================================= /*! The class TSoundOutputDeviceListener permits to notify to other object if a playback is completed. Use it as base class that needs to know if a playback is ended */ class DVAPI TSoundOutputDeviceListener { public: virtual ~TSoundOutputDeviceListener(){}; virtual void onPlayCompleted() = 0; }; //============================================================================== class TSoundOutputDeviceImp; //! \include sndOutDev_ex.cpp /*! The class TSoundOutputDevice permits the playback of a sound track */ class DVAPI TSoundOutputDevice { std::shared_ptr m_imp; public: TSoundOutputDevice(); ~TSoundOutputDevice(); /*! Returns true if on the machine there is an audio card installed correctly */ static bool installed(); //! Returns the best format supported near the given parameters TSoundTrackFormat getPreferredFormat(TUINT32 sampleRate, int channelCount, int bitPerSample, int formatType); //! Returns the best format supported near the given format TSoundTrackFormat getPreferredFormat(const TSoundTrackFormat &); bool isFormatSupported(const TSoundTrackFormat &); #ifndef _WIN32 //! Returns true if is possible to change volume setting on current input //! interface bool supportsVolume(); //! Returns the current value of the volume [0,1] double getVolume(); //! Set the value of volume , between [0,1] bool setVolume(double value); void prepareVolume(double volume); #endif //! Open the device according to the features of soundtrack bool open(const TSoundTrackP &st); //! Playback of the sndtrack in the request sample range void play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop = false, bool scrubbing = false); //! Close in the right mode the device bool close(); /*!Playback of the sndtrack in the request time range. The loop argument permits to set the looping status of player The scrubbing permits to an application to set the mode for the interaction between sound and mouse */ void play(const TSoundTrackP &st, double t0, double t1, bool loop = false, bool scrubbing = false) { play(st, st->secondsToSamples(t0), st->secondsToSamples(t1), loop, scrubbing); } //! Stop the playback of one or more soundtracks void stop(); //! Returns if the device is busy with a playback bool isPlaying() const; #ifdef _WIN32 //! Return true if the playback of all soundtracks is ended. bool isAllQueuedItemsPlayed(); #endif //! Returns if the status of player is in looping bool isLooping(); //! Permits to change the looping status of player void setLooping(bool loop); void attach(TSoundOutputDeviceListener *listener); void detach(TSoundOutputDeviceListener *listener); }; #endif