1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
/*
* ModSampleCopy.h
* ---------------
* Purpose: Functions for copying ModSample data.
* Notes : (currently none)
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
#pragma once
#include "openmpt/all/BuildSettings.hpp"
#include "openmpt/soundbase/SampleDecode.hpp"
OPENMPT_NAMESPACE_BEGIN
struct ModSample;
// Copy a mono sample data buffer.
template <typename SampleConversion, typename Tbyte>
size_t CopyMonoSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, SampleConversion conv = SampleConversion())
{
MPT_ASSERT(sample.GetNumChannels() == 1);
MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
const size_t frameSize = SampleConversion::input_inc;
const size_t countFrames = std::min(sourceSize / frameSize, static_cast<std::size_t>(sample.nLength));
size_t numFrames = countFrames;
SampleConversion sampleConv(conv);
const std::byte * MPT_RESTRICT inBuf = mpt::byte_cast<const std::byte*>(sourceBuffer);
typename SampleConversion::output_t * MPT_RESTRICT outBuf = static_cast<typename SampleConversion::output_t *>(sample.samplev());
while(numFrames--)
{
*outBuf = sampleConv(inBuf);
inBuf += SampleConversion::input_inc;
outBuf++;
}
return frameSize * countFrames;
}
// Copy a stereo interleaved sample data buffer.
template <typename SampleConversion, typename Tbyte>
size_t CopyStereoInterleavedSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, SampleConversion conv = SampleConversion())
{
MPT_ASSERT(sample.GetNumChannels() == 2);
MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
const size_t frameSize = 2 * SampleConversion::input_inc;
const size_t countFrames = std::min(sourceSize / frameSize, static_cast<std::size_t>(sample.nLength));
size_t numFrames = countFrames;
SampleConversion sampleConvLeft(conv);
SampleConversion sampleConvRight(conv);
const std::byte * MPT_RESTRICT inBuf = mpt::byte_cast<const std::byte*>(sourceBuffer);
typename SampleConversion::output_t * MPT_RESTRICT outBuf = static_cast<typename SampleConversion::output_t *>(sample.samplev());
while(numFrames--)
{
*outBuf = sampleConvLeft(inBuf);
inBuf += SampleConversion::input_inc;
outBuf++;
*outBuf = sampleConvRight(inBuf);
inBuf += SampleConversion::input_inc;
outBuf++;
}
return frameSize * countFrames;
}
// Copy a stereo split sample data buffer.
template <typename SampleConversion, typename Tbyte>
size_t CopyStereoSplitSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, SampleConversion conv = SampleConversion())
{
MPT_ASSERT(sample.GetNumChannels() == 2);
MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
const size_t sampleSize = SampleConversion::input_inc;
const size_t sourceSizeLeft = std::min(static_cast<std::size_t>(sample.nLength) * SampleConversion::input_inc, sourceSize);
const size_t sourceSizeRight = std::min(static_cast<std::size_t>(sample.nLength) * SampleConversion::input_inc, sourceSize - sourceSizeLeft);
const size_t countSamplesLeft = sourceSizeLeft / sampleSize;
const size_t countSamplesRight = sourceSizeRight / sampleSize;
size_t numSamplesLeft = countSamplesLeft;
SampleConversion sampleConvLeft(conv);
const std::byte * MPT_RESTRICT inBufLeft = mpt::byte_cast<const std::byte*>(sourceBuffer);
typename SampleConversion::output_t * MPT_RESTRICT outBufLeft = static_cast<typename SampleConversion::output_t *>(sample.samplev());
while(numSamplesLeft--)
{
*outBufLeft = sampleConvLeft(inBufLeft);
inBufLeft += SampleConversion::input_inc;
outBufLeft += 2;
}
size_t numSamplesRight = countSamplesRight;
SampleConversion sampleConvRight(conv);
const std::byte * MPT_RESTRICT inBufRight = mpt::byte_cast<const std::byte*>(sourceBuffer) + sample.nLength * SampleConversion::input_inc;
typename SampleConversion::output_t * MPT_RESTRICT outBufRight = static_cast<typename SampleConversion::output_t *>(sample.samplev()) + 1;
while(numSamplesRight--)
{
*outBufRight = sampleConvRight(inBufRight);
inBufRight += SampleConversion::input_inc;
outBufRight += 2;
}
return (countSamplesLeft + countSamplesRight) * sampleSize;
}
// Copy a sample data buffer and normalize it. Requires slightly advanced sample conversion functor.
template <typename SampleConversion, typename Tbyte>
size_t CopyAndNormalizeSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, typename SampleConversion::peak_t *srcPeak = nullptr, SampleConversion conv = SampleConversion())
{
const size_t sampleSize = SampleConversion::input_inc;
MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
size_t numSamples = sample.nLength * sample.GetNumChannels();
LimitMax(numSamples, sourceSize / sampleSize);
const std::byte * inBuf = mpt::byte_cast<const std::byte*>(sourceBuffer);
// Finding max value
SampleConversion sampleConv(conv);
for(size_t i = numSamples; i != 0; i--)
{
sampleConv.FindMax(inBuf);
inBuf += SampleConversion::input_inc;
}
// If buffer is silent (maximum is 0), don't bother normalizing the sample - just keep the already silent buffer.
if(!sampleConv.IsSilent())
{
inBuf = sourceBuffer;
// Copying buffer.
typename SampleConversion::output_t *outBuf = static_cast<typename SampleConversion::output_t *>(sample.samplev());
for(size_t i = numSamples; i != 0; i--)
{
*outBuf = sampleConv(inBuf);
outBuf++;
inBuf += SampleConversion::input_inc;
}
}
if(srcPeak)
{
*srcPeak = sampleConv.GetSrcPeak();
}
return numSamples * sampleSize;
}
OPENMPT_NAMESPACE_END
|