Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/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
  AudioBlock() {
25
    mDuration = WEBAUDIO_BLOCK_SIZE;
26
    mBufferFormat = AUDIO_FORMAT_SILENCE;
27
  }
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
  AudioBlock(const AudioBlock& aBlock) : AudioChunk(aBlock.AsAudioChunk()) {}
34
  explicit AudioBlock(const AudioChunk& aChunk)
35
    : AudioChunk(aChunk)
36
0
  {
37
0
    MOZ_ASSERT(aChunk.mDuration == WEBAUDIO_BLOCK_SIZE);
38
0
  }
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
  const AudioChunk& AsAudioChunk() const { return *this; }
54
  AudioChunk* AsMutableChunk() {
55
    ClearDownstreamMark();
56
    return this;
57
  }
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
  {
71
    MOZ_ASSERT(mBufferFormat == AUDIO_FORMAT_FLOAT32);
72
    MOZ_ASSERT(CanWrite());
73
    return static_cast<float*>(const_cast<void*>(mChannelData[aChannel]));
74
  }
75
76
  void SetBuffer(ThreadSharedObject* aNewBuffer);
77
  void SetNull(StreamTime aDuration) {
78
    MOZ_ASSERT(aDuration == WEBAUDIO_BLOCK_SIZE);
79
    SetBuffer(nullptr);
80
    mChannelData.Clear();
81
    mVolume = 1.0f;
82
    mBufferFormat = AUDIO_FORMAT_SILENCE;
83
  }
84
85
  AudioBlock& operator=(const AudioBlock& aBlock) {
86
    // Instead of just copying, mBufferIsDownstreamRef must be first cleared
87
    // if set.  It is set again for the new mBuffer if possible.  This happens
88
    // in SetBuffer().
89
    return *this = aBlock.AsAudioChunk();
90
  }
91
  AudioBlock& operator=(const AudioChunk& aChunk) {
92
    MOZ_ASSERT(aChunk.mDuration == WEBAUDIO_BLOCK_SIZE);
93
    SetBuffer(aChunk.mBuffer);
94
    mChannelData = aChunk.mChannelData;
95
    mVolume = aChunk.mVolume;
96
    mBufferFormat = aChunk.mBufferFormat;
97
    return *this;
98
  }
99
100
  bool IsMuted() const { return mVolume == 0.0f; }
101
102
  bool IsSilentOrSubnormal() const
103
  {
104
    if (!mBuffer) {
105
      return true;
106
    }
107
108
    for (uint32_t i = 0, length = mChannelData.Length(); i < length; ++i) {
109
      const float* channel = static_cast<const float*>(mChannelData[i]);
110
      for (StreamTime frame = 0; frame < mDuration; ++frame) {
111
        if (fabs(channel[frame]) >= FLT_MIN) {
112
          return false;
113
        }
114
      }
115
    }
116
117
    return true;
118
  }
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_