/** * Converts the data in aSegment to a single chunk aBlock. aSegment must have * duration WEBAUDIO_BLOCK_SIZE. aFallbackChannelCount is a superset of the * channels in every chunk of aSegment. aBlock must be float format or null. */ static void ConvertSegmentToAudioBlock(AudioSegment* aSegment, AudioChunk* aBlock, int32_t aFallbackChannelCount) { NS_ASSERTION(aSegment->GetDuration() == WEBAUDIO_BLOCK_SIZE, "Bad segment duration"); { AudioSegment::ChunkIterator ci(*aSegment); NS_ASSERTION(!ci.IsEnded(), "Should be at least one chunk!"); if (ci->GetDuration() == WEBAUDIO_BLOCK_SIZE && (ci->IsNull() || ci->mBufferFormat == AUDIO_FORMAT_FLOAT32)) { // Return this chunk directly to avoid copying data. *aBlock = *ci; return; } } AllocateAudioBlock(aFallbackChannelCount, aBlock); uint32_t duration = 0; for (AudioSegment::ChunkIterator ci(*aSegment); !ci.IsEnded(); ci.Next()) { CopyChunkToBlock(*ci, aBlock, duration); duration += ci->GetDuration(); } }
/** * Converts the data in aSegment to a single chunk aChunk. Every chunk in * aSegment must have the same number of channels (or be null). aSegment must have * duration WEBAUDIO_BLOCK_SIZE. Every chunk in aSegment must be in float format. */ static void ConvertSegmentToAudioBlock(AudioSegment* aSegment, AudioChunk* aBlock) { NS_ASSERTION(aSegment->GetDuration() == WEBAUDIO_BLOCK_SIZE, "Bad segment duration"); { AudioSegment::ChunkIterator ci(*aSegment); NS_ASSERTION(!ci.IsEnded(), "Segment must have at least one chunk"); AudioChunk& firstChunk = *ci; ci.Next(); if (ci.IsEnded()) { *aBlock = firstChunk; return; } while (ci->IsNull() && !ci.IsEnded()) { ci.Next(); } if (ci.IsEnded()) { // All null. aBlock->SetNull(WEBAUDIO_BLOCK_SIZE); return; } AllocateAudioBlock(ci->mChannelData.Length(), aBlock); } AudioSegment::ChunkIterator ci(*aSegment); uint32_t duration = 0; while (!ci.IsEnded()) { CopyChunkToBlock(*ci, aBlock, duration); duration += ci->GetDuration(); ci.Next(); } }