1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004-2021 musikcube team
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice,
11 // this list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright
14 // notice, this list of conditions and the following disclaimer in the
15 // documentation and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the author nor the names of other contributors may
18 // be used to endorse or promote products derived from this software
19 // without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 //
33 //////////////////////////////////////////////////////////////////////////////
34
35 #include "pch.hpp"
36
37 #include <musikcore/audio/Buffer.h>
38
39 #ifdef WIN32
40 #define CopyFloat(dst, src, num) CopyMemory(dst, src, (num) * sizeof(float))
41 #else
42 #define CopyFloat(dst, src, num) memcpy((float*) dst, (float*)src, (num) * sizeof(float))
43 #endif
44
45 using namespace musik::core::audio;
46
Buffer(Flags flags)47 Buffer::Buffer(Flags flags) noexcept
48 : buffer(nullptr)
49 , samples(0)
50 , internalBufferSize(0)
51 , sampleRate(44100)
52 , channels(2)
53 , flags(flags)
54 , position(0) {
55 }
56
Buffer(float * buffer,int samples)57 Buffer::Buffer(float* buffer, int samples) noexcept
58 : buffer(buffer)
59 , samples(samples)
60 , internalBufferSize(samples)
61 , sampleRate(44100)
62 , channels(2)
63 , flags(ImmutableSize | NoDelete)
64 , position(0) {
65 }
66
~Buffer()67 Buffer::~Buffer() {
68 if ((flags & NoDelete) == 0) {
69 delete[] this->buffer;
70 }
71 }
72
SampleRate() const73 long Buffer::SampleRate() const noexcept { /* hertz */
74 return this->sampleRate;
75 }
76
SetSampleRate(long sampleRate)77 void Buffer::SetSampleRate(long sampleRate) noexcept { /* hertz */
78 this->sampleRate = sampleRate;
79 }
80
Channels() const81 int Buffer::Channels() const noexcept {
82 return this->channels;
83 }
84
SetChannels(int channels)85 void Buffer::SetChannels(int channels) noexcept {
86 this->channels = channels;
87 }
88
BufferPointer() const89 float* Buffer::BufferPointer() const noexcept {
90 return this->buffer;
91 }
92
Samples() const93 long Buffer::Samples() const noexcept {
94 return this->samples;
95 }
96
SetSamples(long samples)97 void Buffer::SetSamples(long samples) {
98 this->samples = samples;
99 this->ResizeBuffer();
100 }
101
CopyFormat(Buffer * fromBuffer)102 void Buffer::CopyFormat(Buffer* fromBuffer) noexcept {
103 if (fromBuffer) {
104 this->channels = fromBuffer->Channels();
105 this->sampleRate = fromBuffer->SampleRate();
106 }
107 }
108
ResizeBuffer()109 void Buffer::ResizeBuffer() {
110 if (this->samples > this->internalBufferSize) {
111 if (flags & ImmutableSize && this->internalBufferSize > 0) {
112 throw std::runtime_error("buffer cannot be resized");
113 }
114
115 delete[] this->buffer;
116 this->buffer = new float[this->samples];
117 this->internalBufferSize = this->samples;
118 }
119 }
120
121 /* logical bytes; backing store may be be larger */
Bytes() const122 long Buffer::Bytes() const noexcept {
123 return sizeof(float) * this->samples;
124 }
125
Position() const126 double Buffer::Position() const noexcept {
127 return this->position;
128 }
129
SetPosition(double position)130 void Buffer::SetPosition(double position) noexcept {
131 this->position = position;
132 }
133
Copy(float const * buffer,long samples,long offset)134 void Buffer::Copy(float const* buffer, long samples, long offset) {
135 const long length = offset + samples;
136 if (length > this->internalBufferSize) {
137 float *newBuffer = new float[length];
138 CopyFloat(newBuffer, this->buffer, this->internalBufferSize);
139 CopyFloat(newBuffer + offset, buffer, samples);
140 delete[] this->buffer;
141 this->buffer = newBuffer;
142 this->internalBufferSize = length;
143 }
144 else {
145 CopyFloat(this->buffer + offset, buffer, samples);
146 }
147
148 this->samples = std::max(this->samples, length);
149 }