1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef MOZILLA_AUDIOSEGMENT_H_
7 #define MOZILLA_AUDIOSEGMENT_H_
9 #include "MediaSegment.h"
10 #include "AudioSampleFormat.h"
11 #include "SharedBuffer.h"
12 #ifdef MOZILLA_INTERNAL_API
13 #include "mozilla/TimeStamp.h"
21 * For auto-arrays etc, guess this as the common number of channels.
23 const int GUESS_AUDIO_CHANNELS
= 2;
25 // We ensure that the graph advances in steps that are multiples of the Web
27 const uint32_t WEBAUDIO_BLOCK_SIZE_BITS
= 7;
28 const uint32_t WEBAUDIO_BLOCK_SIZE
= 1 << WEBAUDIO_BLOCK_SIZE_BITS
;
30 void InterleaveAndConvertBuffer(const void** aSourceChannels
,
31 AudioSampleFormat aSourceFormat
,
32 int32_t aLength
, float aVolume
,
34 AudioDataValue
* aOutput
);
37 * Given an array of input channels (aChannelData), downmix to aOutputChannels,
38 * interleave the channel data. A total of aOutputChannels*aDuration
39 * interleaved samples will be copied to a channel buffer in aOutput.
41 void DownmixAndInterleave(const nsTArray
<const void*>& aChannelData
,
42 AudioSampleFormat aSourceFormat
, int32_t aDuration
,
43 float aVolume
, uint32_t aOutputChannels
,
44 AudioDataValue
* aOutput
);
47 * An AudioChunk represents a multi-channel buffer of audio samples.
48 * It references an underlying ThreadSharedObject which manages the lifetime
49 * of the buffer. An AudioChunk maintains its own duration and channel data
50 * pointers so it can represent a subinterval of a buffer without copying.
51 * An AudioChunk can store its individual channels anywhere; it maintains
52 * separate pointers to each channel's buffer.
55 typedef mozilla::AudioSampleFormat SampleFormat
;
58 void SliceTo(TrackTicks aStart
, TrackTicks aEnd
)
60 NS_ASSERTION(aStart
>= 0 && aStart
< aEnd
&& aEnd
<= mDuration
,
61 "Slice out of bounds");
63 MOZ_ASSERT(aStart
< INT32_MAX
, "Can't slice beyond 32-bit sample lengths");
64 for (uint32_t channel
= 0; channel
< mChannelData
.Length(); ++channel
) {
65 mChannelData
[channel
] = AddAudioSampleOffset(mChannelData
[channel
],
66 mBufferFormat
, int32_t(aStart
));
69 mDuration
= aEnd
- aStart
;
71 TrackTicks
GetDuration() const { return mDuration
; }
72 bool CanCombineWithFollowing(const AudioChunk
& aOther
) const
74 if (aOther
.mBuffer
!= mBuffer
) {
78 NS_ASSERTION(aOther
.mBufferFormat
== mBufferFormat
,
79 "Wrong metadata about buffer");
80 NS_ASSERTION(aOther
.mChannelData
.Length() == mChannelData
.Length(),
81 "Mismatched channel count");
82 if (mDuration
> INT32_MAX
) {
85 for (uint32_t channel
= 0; channel
< mChannelData
.Length(); ++channel
) {
86 if (aOther
.mChannelData
[channel
] != AddAudioSampleOffset(mChannelData
[channel
],
87 mBufferFormat
, int32_t(mDuration
))) {
94 bool IsNull() const { return mBuffer
== nullptr; }
95 void SetNull(TrackTicks aDuration
)
99 mDuration
= aDuration
;
103 TrackTicks mDuration
; // in frames within the buffer
104 nsRefPtr
<ThreadSharedObject
> mBuffer
; // the buffer object whose lifetime is managed; null means data is all zeroes
105 nsTArray
<const void*> mChannelData
; // one pointer per channel; empty if and only if mBuffer is null
106 float mVolume
; // volume multiplier to apply (1.0f if mBuffer is nonnull)
107 SampleFormat mBufferFormat
; // format of frames in mBuffer (only meaningful if mBuffer is nonnull)
108 #ifdef MOZILLA_INTERNAL_API
109 mozilla::TimeStamp mTimeStamp
; // time at which this has been fetched from the MediaEngine
114 * A list of audio samples consisting of a sequence of slices of SharedBuffers.
115 * The audio rate is determined by the track, not stored in this class.
117 class AudioSegment
: public MediaSegmentBase
<AudioSegment
, AudioChunk
> {
119 typedef mozilla::AudioSampleFormat SampleFormat
;
121 AudioSegment() : MediaSegmentBase
<AudioSegment
, AudioChunk
>(AUDIO
) {}
123 void AppendFrames(already_AddRefed
<ThreadSharedObject
> aBuffer
,
124 const nsTArray
<const float*>& aChannelData
,
127 AudioChunk
* chunk
= AppendChunk(aDuration
);
128 chunk
->mBuffer
= aBuffer
;
129 for (uint32_t channel
= 0; channel
< aChannelData
.Length(); ++channel
) {
130 chunk
->mChannelData
.AppendElement(aChannelData
[channel
]);
132 chunk
->mVolume
= 1.0f
;
133 chunk
->mBufferFormat
= AUDIO_FORMAT_FLOAT32
;
134 #ifdef MOZILLA_INTERNAL_API
135 chunk
->mTimeStamp
= TimeStamp::Now();
138 void AppendFrames(already_AddRefed
<ThreadSharedObject
> aBuffer
,
139 const nsTArray
<const int16_t*>& aChannelData
,
142 AudioChunk
* chunk
= AppendChunk(aDuration
);
143 chunk
->mBuffer
= aBuffer
;
144 for (uint32_t channel
= 0; channel
< aChannelData
.Length(); ++channel
) {
145 chunk
->mChannelData
.AppendElement(aChannelData
[channel
]);
147 chunk
->mVolume
= 1.0f
;
148 chunk
->mBufferFormat
= AUDIO_FORMAT_S16
;
149 #ifdef MOZILLA_INTERNAL_API
150 chunk
->mTimeStamp
= TimeStamp::Now();
153 // Consumes aChunk, and returns a pointer to the persistent copy of aChunk
155 AudioChunk
* AppendAndConsumeChunk(AudioChunk
* aChunk
)
157 AudioChunk
* chunk
= AppendChunk(aChunk
->mDuration
);
158 chunk
->mBuffer
= aChunk
->mBuffer
.forget();
159 chunk
->mChannelData
.SwapElements(aChunk
->mChannelData
);
160 chunk
->mVolume
= aChunk
->mVolume
;
161 chunk
->mBufferFormat
= aChunk
->mBufferFormat
;
162 #ifdef MOZILLA_INTERNAL_API
163 chunk
->mTimeStamp
= TimeStamp::Now();
167 void ApplyVolume(float aVolume
);
168 void WriteTo(uint64_t aID
, AudioStream
* aOutput
);
170 static Type
StaticType() { return AUDIO
; }
175 #endif /* MOZILLA_AUDIOSEGMENT_H_ */