summaryrefslogtreecommitdiffstats
path: root/src/multimedia/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/audio')
-rw-r--r--src/multimedia/audio/qaudiobuffer.cpp118
-rw-r--r--src/multimedia/audio/qaudiobuffer.h33
-rw-r--r--src/multimedia/audio/qaudiobuffer_p.h2
-rw-r--r--src/multimedia/audio/qaudioformat.cpp112
-rw-r--r--src/multimedia/audio/qaudioformat.h12
5 files changed, 206 insertions, 71 deletions
diff --git a/src/multimedia/audio/qaudiobuffer.cpp b/src/multimedia/audio/qaudiobuffer.cpp
index bde04501f..299a610fa 100644
--- a/src/multimedia/audio/qaudiobuffer.cpp
+++ b/src/multimedia/audio/qaudiobuffer.cpp
@@ -106,18 +106,18 @@ public:
// Private class to go in .cpp file
class QMemoryAudioBufferProvider : public QAbstractAudioBuffer {
public:
- QMemoryAudioBufferProvider(const void *data, int sampleCount, const QAudioFormat &format, qint64 startTime)
+ QMemoryAudioBufferProvider(const void *data, int frameCount, const QAudioFormat &format, qint64 startTime)
: mStartTime(startTime)
- , mSampleCount(sampleCount)
+ , mFrameCount(frameCount)
, mFormat(format)
{
- int numBytes = (sampleCount * format.sampleSize()) / 8;
+ int numBytes = format.bytesForFrames(frameCount);
if (numBytes > 0) {
mBuffer = malloc(numBytes);
if (!mBuffer) {
// OOM, if that's likely
mStartTime = -1;
- mSampleCount = 0;
+ mFrameCount = 0;
mFormat = QAudioFormat();
} else {
// Allocated, see if we have data to copy
@@ -149,19 +149,19 @@ public:
void release() {delete this;}
QAudioFormat format() const {return mFormat;}
qint64 startTime() const {return mStartTime;}
- int sampleCount() const {return mSampleCount;}
+ int frameCount() const {return mFrameCount;}
void *constData() const {return mBuffer;}
void *writableData() {return mBuffer;}
QAbstractAudioBuffer *clone() const
{
- return new QMemoryAudioBufferProvider(mBuffer, mSampleCount, mFormat, mStartTime);
+ return new QMemoryAudioBufferProvider(mBuffer, mFrameCount, mFormat, mStartTime);
}
void *mBuffer;
qint64 mStartTime;
- int mSampleCount;
+ int mFrameCount;
QAudioFormat mFormat;
};
@@ -176,7 +176,7 @@ QAudioBufferPrivate *QAudioBufferPrivate::clone()
QAbstractAudioBuffer *abuf = mProvider->clone();
if (!abuf) {
- abuf = new QMemoryAudioBufferProvider(mProvider->constData(), mProvider->sampleCount(), mProvider->format(), mProvider->startTime());
+ abuf = new QMemoryAudioBufferProvider(mProvider->constData(), mProvider->frameCount(), mProvider->format(), mProvider->startTime());
}
if (abuf) {
@@ -236,7 +236,7 @@ QAudioBuffer::QAudioBuffer(const QAudioBuffer &other)
and sizes of the samples are interpreted from the \a data.
If the supplied \a data is not an integer multiple of the
- calculated sample size, the excess data will not be used.
+ calculated frame size, the excess data will not be used.
This audio buffer will copy the contents of \a data.
@@ -247,25 +247,25 @@ QAudioBuffer::QAudioBuffer(const QAudioBuffer &other)
QAudioBuffer::QAudioBuffer(const QByteArray &data, const QAudioFormat &format, qint64 startTime)
{
if (format.isValid()) {
- int sampleCount = (data.size() * 8) / format.sampleSize(); // truncate
- d = new QAudioBufferPrivate(new QMemoryAudioBufferProvider(data.constData(), sampleCount, format, startTime));
+ int frameCount = format.framesForBytes(data.size());
+ d = new QAudioBufferPrivate(new QMemoryAudioBufferProvider(data.constData(), frameCount, format, startTime));
} else
d = 0;
}
/*!
- Creates a new audio buffer with space for \a numSamples samples of
- the given \a format. The samples will be initialized to the default
- for the format.
+ Creates a new audio buffer with space for \a numFrames frames of
+ the given \a format. The individual samples will be initialized
+ to the default for the format.
\a startTime (in microseconds) indicates when this buffer
starts in the stream.
If this buffer is not part of a stream, set it to -1.
*/
-QAudioBuffer::QAudioBuffer(int numSamples, const QAudioFormat &format, qint64 startTime)
+QAudioBuffer::QAudioBuffer(int numFrames, const QAudioFormat &format, qint64 startTime)
{
if (format.isValid())
- d = new QAudioBufferPrivate(new QMemoryAudioBufferProvider(0, numSamples, format, startTime));
+ d = new QAudioBufferPrivate(new QMemoryAudioBufferProvider(0, numFrames, format, startTime));
else
d = 0;
}
@@ -292,13 +292,13 @@ QAudioBuffer::~QAudioBuffer()
/*!
Returns true if this is a valid buffer. A valid buffer
- has more than zero samples in it and a valid format.
+ has more than zero frames in it and a valid format.
*/
bool QAudioBuffer::isValid() const
{
if (!d || !d->mProvider)
return false;
- return d->mProvider->format().isValid() && (d->mProvider->sampleCount() > 0);
+ return d->mProvider->format().isValid() && (d->mProvider->frameCount() > 0);
}
/*!
@@ -306,7 +306,7 @@ bool QAudioBuffer::isValid() const
Several properties of this format influence how
the \l duration() or \l byteCount() are calculated
- from the \l sampleCount().
+ from the \l frameCount().
*/
QAudioFormat QAudioBuffer::format() const
{
@@ -316,6 +316,19 @@ QAudioFormat QAudioBuffer::format() const
}
/*!
+ Returns the number of complete audio frames in this buffer.
+
+ An audio frame is an interleaved set of one sample per channel
+ for the same instant in time.
+*/
+int QAudioBuffer::frameCount() const
+{
+ if (!isValid())
+ return 0;
+ return d->mProvider->frameCount();
+}
+
+/*!
Returns the number of samples in this buffer.
If the format of this buffer has multiple channels,
@@ -323,12 +336,15 @@ QAudioFormat QAudioBuffer::format() const
that a stereo buffer with 1000 samples in total will
have 500 left samples and 500 right samples (interleaved),
and this function will return 1000.
- */
+
+ \sa frameCount()
+*/
int QAudioBuffer::sampleCount() const
{
if (!isValid())
return 0;
- return d->mProvider->sampleCount();
+
+ return frameCount() * format().channelCount();
}
/*!
@@ -337,21 +353,17 @@ int QAudioBuffer::sampleCount() const
int QAudioBuffer::byteCount() const
{
const QAudioFormat f(format());
- return (f.sampleSize() * sampleCount()) / 8; // sampleSize is in bits
+ return format().bytesForFrames(frameCount());
}
/*!
Returns the duration of audio in this buffer, in microseconds.
- This depends on the /l format(), and the \l sampleCount().
+ This depends on the /l format(), and the \l frameCount().
*/
qint64 QAudioBuffer::duration() const
{
- int divisor = format().sampleRate() * format().channelCount();
- if (divisor > 0)
- return (sampleCount() * 1000000LL) / divisor;
- else
- return 0;
+ return format().durationForFrames(frameCount());
}
/*!
@@ -471,7 +483,7 @@ void *QAudioBuffer::data()
}
// Wasn't writable, so turn it into a memory provider
- QAbstractAudioBuffer *memBuffer = new QMemoryAudioBufferProvider(constData(), sampleCount(), format(), startTime());
+ QAbstractAudioBuffer *memBuffer = new QMemoryAudioBufferProvider(constData(), frameCount(), format(), startTime());
if (memBuffer) {
d->mProvider->release();
@@ -487,35 +499,35 @@ void *QAudioBuffer::data()
// Template helper classes worth documenting
/*!
- \class QAudioBuffer::StereoSampleDefault
+ \class QAudioBuffer::StereoFrameDefault
\internal
Just a trait class for the default value.
*/
/*!
- \class QAudioBuffer::StereoSample
- \brief The StereoSample class provides a simple wrapper for a stereo audio sample.
+ \class QAudioBuffer::StereoFrame
+ \brief The StereoFrame class provides a simple wrapper for a stereo audio frame.
\inmodule QtMultimedia
\ingroup multimedia
\ingroup multimedia_audio
This templatized structure lets you treat a block of individual samples as an
- interleaved stereo stream. This is most useful when used with the templatized
+ interleaved stereo stream frame. This is most useful when used with the templatized
\l {QAudioBuffer::data()}{data()} functions of QAudioBuffer. Generally the data
is accessed as a pointer, so no copying should occur.
There are some predefined instantiations of this template for working with common
stereo sample depths in a convenient way.
- This structure has \e left and \e right members for accessing individual channel data.
+ This frame structure has \e left and \e right members for accessing individual channel data.
For example:
\code
// Assuming 'buffer' is an unsigned 16 bit stereo buffer..
- QAudioBuffer::S16U *sample = buffer->data<QAudioBuffer::S16U>();
- for (int i=0; i < buffer->sampleCount() / 2; i++) {
- qSwap(sample[i].left, sample[i].right);
+ QAudioBuffer::S16U *frames = buffer->data<QAudioBuffer::S16U>();
+ for (int i=0; i < buffer->frameCount(); i++) {
+ qSwap(frames[i].left, frames[i].right);
}
\endcode
@@ -523,77 +535,77 @@ void *QAudioBuffer::data()
*/
/*!
- \fn QAudioBuffer::StereoSample::StereoSample()
+ \fn QAudioBuffer::StereoFrame::StereoFrame()
- Constructs a new sample with the "silent" value for this
+ Constructs a new frame with the "silent" value for this
sample format (0 for signed formats and floats, 0x8* for unsigned formats).
*/
/*!
- \fn QAudioBuffer::StereoSample::StereoSample(T leftSample, T rightSample)
+ \fn QAudioBuffer::StereoFrame::StereoFrame(T leftSample, T rightSample)
- Constructs a new sample with the supplied \a leftSample and \a rightSample values.
+ Constructs a new frame with the supplied \a leftSample and \a rightSample values.
*/
/*!
- \fn QAudioBuffer::StereoSample::operator=(const StereoSample &other)
+ \fn QAudioBuffer::StereoFrame::operator=(const StereoFrame &other)
- Assigns \a other to this sample.
+ Assigns \a other to this frame.
*/
/*!
- \fn QAudioBuffer::StereoSample::average() const
+ \fn QAudioBuffer::StereoFrame::average() const
Returns the arithmetic average of the left and right samples.
*/
-/*! \fn QAudioBuffer::StereoSample::clear()
+/*! \fn QAudioBuffer::StereoFrame::clear()
- Sets the values of this sample to the "silent" value.
+ Sets the values of this frame to the "silent" value.
*/
/*!
- \variable QAudioBuffer::StereoSample::left
+ \variable QAudioBuffer::StereoFrame::left
\brief the left sample
*/
/*!
- \variable QAudioBuffer::StereoSample::right
+ \variable QAudioBuffer::StereoFrame::right
\brief the right sample
*/
/*!
\typedef QAudioBuffer::S8U
- \relates QAudioBuffer::StereoSample
+ \relates QAudioBuffer::StereoFrame
This is a predefined specialization for an unsigned stereo 8 bit sample. Each
channel is an \e {unsigned char}.
*/
/*!
\typedef QAudioBuffer::S8S
- \relates QAudioBuffer::StereoSample
+ \relates QAudioBuffer::StereoFrame
This is a predefined specialization for a signed stereo 8 bit sample. Each
channel is a \e {signed char}.
*/
/*!
\typedef QAudioBuffer::S16U
- \relates QAudioBuffer::StereoSample
+ \relates QAudioBuffer::StereoFrame
This is a predefined specialization for an unsigned stereo 16 bit sample. Each
channel is an \e {unsigned short}.
*/
/*!
\typedef QAudioBuffer::S16S
- \relates QAudioBuffer::StereoSample
+ \relates QAudioBuffer::StereoFrame
This is a predefined specialization for a signed stereo 16 bit sample. Each
channel is a \e {signed short}.
*/
/*!
\typedef QAudioBuffer::S32F
- \relates QAudioBuffer::StereoSample
+ \relates QAudioBuffer::StereoFrame
This is a predefined specialization for an 32 bit float sample. Each
channel is a \e float.
diff --git a/src/multimedia/audio/qaudiobuffer.h b/src/multimedia/audio/qaudiobuffer.h
index 14718cb38..ac16e2182 100644
--- a/src/multimedia/audio/qaudiobuffer.h
+++ b/src/multimedia/audio/qaudiobuffer.h
@@ -65,7 +65,7 @@ public:
QAudioBuffer(QAbstractAudioBuffer *provider);
QAudioBuffer(const QAudioBuffer &other);
QAudioBuffer(const QByteArray &data, const QAudioFormat &format, qint64 startTime = -1);
- QAudioBuffer(int numSamples, const QAudioFormat &format, qint64 startTime = -1); // Initialized to empty
+ QAudioBuffer(int numFrames, const QAudioFormat &format, qint64 startTime = -1); // Initialized to empty
QAudioBuffer& operator=(const QAudioBuffer &other);
@@ -75,6 +75,7 @@ public:
QAudioFormat format() const;
+ int frameCount() const;
int sampleCount() const;
int byteCount() const;
@@ -93,23 +94,23 @@ public:
void *data(); // detaches
// Structures for easier access to stereo data
- template <typename T> struct StereoSampleDefault { enum { Default = 0 }; };
+ template <typename T> struct StereoFrameDefault { enum { Default = 0 }; };
- template <typename T> struct StereoSample {
+ template <typename T> struct StereoFrame {
- StereoSample()
- : left(T(StereoSampleDefault<T>::Default))
- , right(T(StereoSampleDefault<T>::Default))
+ StereoFrame()
+ : left(T(StereoFrameDefault<T>::Default))
+ , right(T(StereoFrameDefault<T>::Default))
{
}
- StereoSample(T leftSample, T rightSample)
+ StereoFrame(T leftSample, T rightSample)
: left(leftSample)
, right(rightSample)
{
}
- StereoSample& operator=(const StereoSample &other)
+ StereoFrame& operator=(const StereoFrame &other)
{
// Two straight assigns is probably
// cheaper than a conditional check on
@@ -123,14 +124,14 @@ public:
T right;
T average() const {return (left + right) / 2;}
- void clear() {left = right = T(StereoSampleDefault<T>::Default);}
+ void clear() {left = right = T(StereoFrameDefault<T>::Default);}
};
- typedef StereoSample<unsigned char> S8U;
- typedef StereoSample<signed char> S8S;
- typedef StereoSample<unsigned short> S16U;
- typedef StereoSample<signed short> S16S;
- typedef StereoSample<float> S32F;
+ typedef StereoFrame<unsigned char> S8U;
+ typedef StereoFrame<signed char> S8S;
+ typedef StereoFrame<unsigned short> S16U;
+ typedef StereoFrame<signed short> S16S;
+ typedef StereoFrame<float> S32F;
template <typename T> const T* constData() const {
return static_cast<const T*>(constData());
@@ -145,8 +146,8 @@ private:
QAudioBufferPrivate *d;
};
-template <> struct QAudioBuffer::StereoSampleDefault<unsigned char> { enum { Default = 128 }; };
-template <> struct QAudioBuffer::StereoSampleDefault<unsigned short> { enum { Default = 32768 }; };
+template <> struct QAudioBuffer::StereoFrameDefault<unsigned char> { enum { Default = 128 }; };
+template <> struct QAudioBuffer::StereoFrameDefault<unsigned short> { enum { Default = 32768 }; };
QT_END_NAMESPACE
diff --git a/src/multimedia/audio/qaudiobuffer_p.h b/src/multimedia/audio/qaudiobuffer_p.h
index 854ca23fc..5f6d3168a 100644
--- a/src/multimedia/audio/qaudiobuffer_p.h
+++ b/src/multimedia/audio/qaudiobuffer_p.h
@@ -66,7 +66,7 @@ public:
// Format related
virtual QAudioFormat format() const = 0;
virtual qint64 startTime() const = 0;
- virtual int sampleCount() const = 0;
+ virtual int frameCount() const = 0;
// R/O Data
virtual void *constData() const = 0;
diff --git a/src/multimedia/audio/qaudioformat.cpp b/src/multimedia/audio/qaudioformat.cpp
index c91620b37..32e17a9f9 100644
--- a/src/multimedia/audio/qaudioformat.cpp
+++ b/src/multimedia/audio/qaudioformat.cpp
@@ -146,7 +146,8 @@ public:
This class is typically used in conjunction with QAudioInput or
QAudioOutput to allow you to specify the parameters of the audio
- stream being read or written.
+ stream being read or written, or with QAudioBuffer when dealing with
+ samples in memory.
You can obtain audio formats compatible with the audio device used
through functions in QAudioDeviceInfo. This class also lets you
@@ -154,6 +155,11 @@ public:
the parameters yourself. See the \l QAudioDeviceInfo class
description for details. You need to know the format of the audio
streams you wish to play or record.
+
+ In the common case of interleaved linear PCM data, the codec will
+ be "audio/pcm", and the samples for all channels will be interleaved.
+ One sample for each channel for the same instant in time is referred
+ to as a frame in QtMultimedia (and other places).
*/
/*!
@@ -282,6 +288,8 @@ void QAudioFormat::setSampleSize(int sampleSize)
/*!
Returns the current sample size value, in bits.
+
+ \sa bytesPerFrame()
*/
int QAudioFormat::sampleSize() const
{
@@ -345,6 +353,108 @@ QAudioFormat::SampleType QAudioFormat::sampleType() const
}
/*!
+ Returns the number of bytes required for this audio format for \a duration microseconds.
+
+ Returns 0 if this format is not valid.
+
+ Note that some rounding may occur if \a duration is not an exact fraction of the
+ sampleRate().
+
+ \sa durationForBytes()
+ */
+qint32 QAudioFormat::bytesForDuration(qint64 duration) const
+{
+ return bytesPerFrame() * framesForDuration(duration);
+}
+
+/*!
+ Returns the number of microseconds represented by \a bytes in this format.
+
+ Returns 0 if this format is not valid.
+
+ Note that some rounding may occur if \a bytes is not an exact multiple
+ of the number of bytes per frame.
+
+ \sa bytesForDuration()
+*/
+qint64 QAudioFormat::durationForBytes(qint32 bytes) const
+{
+ if (!isValid() || bytes <= 0)
+ return 0;
+
+ // We round the byte count to ensure whole frames
+ return qint64(1000000LL * (bytes / bytesPerFrame())) / sampleRate();
+}
+
+/*!
+ Returns the number of bytes required for \a frameCount frames of this format.
+
+ Returns 0 if this format is not valid.
+
+ \sa bytesForDuration()
+*/
+qint32 QAudioFormat::bytesForFrames(qint32 frameCount) const
+{
+ return frameCount * bytesPerFrame();
+}
+
+/*!
+ Returns the number of frames represented by \a byteCount in this format.
+
+ Note that some rounding may occur if \a byteCount is not an exact multiple
+ of the number of bytes per frame.
+
+ Each frame has one sample per channel.
+
+ \sa framesForDuration()
+*/
+qint32 QAudioFormat::framesForBytes(qint32 byteCount) const
+{
+ int size = bytesPerFrame();
+ if (size > 0)
+ return byteCount / size;
+ return 0;
+}
+
+/*!
+ Returns the number of frames required to represent \a duration microseconds in this format.
+
+ Note that some rounding may occur if \a duration is not an exact fraction of the
+ \l sampleRate().
+*/
+qint32 QAudioFormat::framesForDuration(qint64 duration) const
+{
+ if (!isValid())
+ return 0;
+
+ return qint32((duration * sampleRate()) / 1000000LL);
+}
+
+/*!
+ Return the number of microseconds represented by \a frameCount frames in this format.
+*/
+qint64 QAudioFormat::durationForFrames(qint32 frameCount) const
+{
+ if (!isValid() || frameCount <= 0)
+ return 0;
+
+ return (frameCount * 1000000LL) / sampleRate();
+}
+
+/*!
+ Returns the number of bytes required to represent one frame (a sample in each channel) in this format.
+
+ Returns 0 if this format is invalid.
+*/
+int QAudioFormat::bytesPerFrame() const
+{
+ if (!isValid())
+ return 0;
+
+ return (sampleSize() * channelCount()) / 8;
+}
+
+/*!
\enum QAudioFormat::SampleType
\value Unknown Not Set
diff --git a/src/multimedia/audio/qaudioformat.h b/src/multimedia/audio/qaudioformat.h
index 3bc5780d6..fccb206eb 100644
--- a/src/multimedia/audio/qaudioformat.h
+++ b/src/multimedia/audio/qaudioformat.h
@@ -91,6 +91,18 @@ public:
void setSampleType(QAudioFormat::SampleType sampleType);
QAudioFormat::SampleType sampleType() const;
+ // Helper functions
+ qint32 bytesForDuration(qint64 duration) const;
+ qint64 durationForBytes(qint32 byteCount) const;
+
+ qint32 bytesForFrames(qint32 frameCount) const;
+ qint32 framesForBytes(qint32 byteCount) const;
+
+ qint32 framesForDuration(qint64 duration) const;
+ qint64 durationForFrames(qint32 frameCount) const;
+
+ int bytesPerFrame() const;
+
private:
QSharedDataPointer<QAudioFormatPrivate> d;
};