Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/webaudio/AudioBlock.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim:set ts=2 sw=2 sts=2 et cindent: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
#ifndef MOZILLA_AUDIOBLOCK_H_
7
#define MOZILLA_AUDIOBLOCK_H_
8
9
#include "AudioSegment.h"
10
11
namespace mozilla {
12
13
/**
14
 * An AudioChunk whose buffer contents need to be valid only for one
15
 * processing block iteration, after which contents can be overwritten if the
16
 * buffer has not been passed to longer term storage or to another thread,
17
 * which may happen though AsAudioChunk() or AsMutableChunk().
18
 *
19
 * Use on graph thread only.
20
 */
21
class AudioBlock : private AudioChunk
22
{
23
public:
24
0
  AudioBlock() {
25
0
    mDuration = WEBAUDIO_BLOCK_SIZE;
26
0
    mBufferFormat = AUDIO_FORMAT_SILENCE;
27
0
  }
28
  // No effort is made in constructors to ensure that mBufferIsDownstreamRef
29
  // is set because the block is expected to be a temporary and so the
30
  // reference will be released before the next iteration.
31
  // The custom copy constructor is required so as not to set
32
  // mBufferIsDownstreamRef without notifying AudioBlockBuffer.
33
0
  AudioBlock(const AudioBlock& aBlock) : AudioChunk(aBlock.AsAudioChunk()) {}
34
  explicit AudioBlock(const AudioChunk& aChunk)
35
    : AudioChunk(aChunk)
36
  {
37
    MOZ_ASSERT(aChunk.mDuration == WEBAUDIO_BLOCK_SIZE);
38
  }
39
  ~AudioBlock();
40
41
  using AudioChunk::GetDuration;
42
  using AudioChunk::IsNull;
43
  using AudioChunk::ChannelCount;
44
  using AudioChunk::ChannelData;
45
  using AudioChunk::SizeOfExcludingThisIfUnshared;
46
  using AudioChunk::SizeOfExcludingThis;
47
  // mDuration is not exposed.  Use GetDuration().
48
  // mBuffer is not exposed.  Use SetBuffer().
49
  using AudioChunk::mChannelData;
50
  using AudioChunk::mVolume;
51
  using AudioChunk::mBufferFormat;
52
53
0
  const AudioChunk& AsAudioChunk() const { return *this; }
54
0
  AudioChunk* AsMutableChunk() {
55
0
    ClearDownstreamMark();
56
0
    return this;
57
0
  }
58
59
  /**
60
   * Allocates, if necessary, aChannelCount buffers of WEBAUDIO_BLOCK_SIZE float
61
   * samples for writing.
62
   */
63
  void AllocateChannels(uint32_t aChannelCount);
64
65
  /**
66
   * ChannelFloatsForWrite() should only be used when the buffers have been
67
   * created with AllocateChannels().
68
   */
69
  float* ChannelFloatsForWrite(size_t aChannel)
70
0
  {
71
0
    MOZ_ASSERT(mBufferFormat == AUDIO_FORMAT_FLOAT32);
72
0
    MOZ_ASSERT(CanWrite());
73
0
    return static_cast<float*>(const_cast<void*>(mChannelData[aChannel]));
74
0
  }
75
76
  void SetBuffer(ThreadSharedObject* aNewBuffer);
77
0
  void SetNull(StreamTime aDuration) {
78
0
    MOZ_ASSERT(aDuration == WEBAUDIO_BLOCK_SIZE);
79
0
    SetBuffer(nullptr);
80
0
    mChannelData.Clear();
81
0
    mVolume = 1.0f;
82
0
    mBufferFormat = AUDIO_FORMAT_SILENCE;
83
0
  }
84
85
0
  AudioBlock& operator=(const AudioBlock& aBlock) {
86
0
    // Instead of just copying, mBufferIsDownstreamRef must be first cleared
87
0
    // if set.  It is set again for the new mBuffer if possible.  This happens
88
0
    // in SetBuffer().
89
0
    return *this = aBlock.AsAudioChunk();
90
0
  }
91
0
  AudioBlock& operator=(const AudioChunk& aChunk) {
92
0
    MOZ_ASSERT(aChunk.mDuration == WEBAUDIO_BLOCK_SIZE);
93
0
    SetBuffer(aChunk.mBuffer);
94
0
    mChannelData = aChunk.mChannelData;
95
0
    mVolume = aChunk.mVolume;
96
0
    mBufferFormat = aChunk.mBufferFormat;
97
0
    return *this;
98
0
  }
99
100
0
  bool IsMuted() const { return mVolume == 0.0f; }
101
102
  bool IsSilentOrSubnormal() const
103
0
  {
104
0
    if (!mBuffer) {
105
0
      return true;
106
0
    }
107
0
108
0
    for (uint32_t i = 0, length = mChannelData.Length(); i < length; ++i) {
109
0
      const float* channel = static_cast<const float*>(mChannelData[i]);
110
0
      for (StreamTime frame = 0; frame < mDuration; ++frame) {
111
0
        if (fabs(channel[frame]) >= FLT_MIN) {
112
0
          return false;
113
0
        }
114
0
      }
115
0
    }
116
0
117
0
    return true;
118
0
  }
119
120
private:
121
  void ClearDownstreamMark();
122
  bool CanWrite();
123
124
  // mBufferIsDownstreamRef is set only when mBuffer references an
125
  // AudioBlockBuffer created in a different AudioBlock.  That can happen when
126
  // this AudioBlock is on a node downstream from the node which created the
127
  // buffer.  When this is set, the AudioBlockBuffer is notified that this
128
  // reference does not prevent the upstream node from re-using the buffer next
129
  // iteration and modifying its contents.  The AudioBlockBuffer is also
130
  // notified when mBuffer releases this reference.
131
  bool mBufferIsDownstreamRef = false;
132
};
133
134
} // namespace mozilla
135
136
DECLARE_USE_COPY_CONSTRUCTORS(mozilla::AudioBlock)
137
138
#endif // MOZILLA_AUDIOBLOCK_H_