Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
8edde7a4
Commit
8edde7a4
authored
Dec 22, 2013
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pcm/Volume: convert to class
Prepare for adding state.
parent
d11a0c9f
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
233 additions
and
273 deletions
+233
-273
Makefile.am
Makefile.am
+3
-1
ReplayGainFilterPlugin.cxx
src/filter/ReplayGainFilterPlugin.cxx
+17
-42
VolumeFilterPlugin.cxx
src/filter/VolumeFilterPlugin.cxx
+13
-50
Volume.cxx
src/pcm/Volume.cxx
+58
-29
Volume.hxx
src/pcm/Volume.hxx
+68
-11
read_mixer.cxx
test/read_mixer.cxx
+0
-9
software_volume.cxx
test/software_volume.cxx
+12
-8
test_pcm_volume.cxx
test/test_pcm_volume.cxx
+62
-123
No files found.
Makefile.am
View file @
8edde7a4
...
...
@@ -1397,7 +1397,7 @@ endif
test_software_volume_SOURCES
=
test
/software_volume.cxx
\
test
/stdbin.h
\
src/CheckAudioFormat.cxx
\
src/
AudioFormat.cxx src/
CheckAudioFormat.cxx
\
src/AudioParser.cxx
test_software_volume_LDADD
=
\
$(PCM_LIBS)
\
...
...
@@ -1484,6 +1484,7 @@ test_read_mixer_SOURCES = test/read_mixer.cxx \
src/Log.cxx src/LogBackend.cxx
\
src/MixerControl.cxx
\
src/FilterPlugin.cxx
\
src/AudioFormat.cxx
\
src/filter/VolumeFilterPlugin.cxx
if
ENABLE_BZIP2_TEST
...
...
@@ -1538,6 +1539,7 @@ test_test_mixramp_LDADD = \
$(CPPUNIT_LIBS)
test_test_pcm_SOURCES
=
\
src/AudioFormat.cxx
\
test
/test_pcm_util.hxx
\
test
/test_pcm_dither.cxx
\
test
/test_pcm_pack.cxx
\
...
...
src/filter/ReplayGainFilterPlugin.cxx
View file @
8edde7a4
...
...
@@ -28,6 +28,7 @@
#include "MixerControl.hxx"
#include "pcm/Volume.hxx"
#include "pcm/PcmBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
...
...
@@ -55,8 +56,8 @@ class ReplayGainFilter final : public Filter {
ReplayGainInfo
info
;
/**
*
The current volume, between 0 and a value that may or may not exceed
* #PCM_VOLUME_1.
*
About the current volume: it is between 0 and a value that
*
may or may not exceed
#PCM_VOLUME_1.
*
* If the default value of true is used for replaygain_limit, the
* application of the volume to the signal will never cause clipping.
...
...
@@ -66,16 +67,11 @@ class ReplayGainFilter final : public Filter {
* maintain a consistent audio level. Whether clipping will actually
* occur depends on what value the user is using for replaygain_preamp.
*/
unsigned
volume
;
AudioFormat
format
;
PcmBuffer
buffer
;
PcmVolume
pv
;
public
:
ReplayGainFilter
()
:
mixer
(
nullptr
),
mode
(
REPLAY_GAIN_OFF
),
volume
(
PCM_VOLUME_1
)
{
:
mixer
(
nullptr
),
mode
(
REPLAY_GAIN_OFF
)
{
info
.
Clear
();
}
...
...
@@ -125,6 +121,7 @@ public:
void
ReplayGainFilter
::
Update
()
{
unsigned
volume
=
PCM_VOLUME_1
;
if
(
mode
!=
REPLAY_GAIN_OFF
)
{
const
auto
&
tuple
=
info
.
tuples
[
mode
];
float
scale
=
tuple
.
CalculateScale
(
replay_gain_preamp
,
...
...
@@ -134,8 +131,9 @@ ReplayGainFilter::Update()
"scale=%f
\n
"
,
(
double
)
scale
);
volume
=
pcm_float_to_volume
(
scale
);
}
else
volume
=
PCM_VOLUME_1
;
}
pv
.
SetVolume
(
volume
);
if
(
mixer
!=
nullptr
)
{
/* update the hardware mixer volume */
...
...
@@ -160,48 +158,25 @@ replay_gain_filter_init(gcc_unused const config_param ¶m,
AudioFormat
ReplayGainFilter
::
Open
(
AudioFormat
&
af
,
gcc_unused
Error
&
error
)
{
format
=
af
;
if
(
!
pv
.
Open
(
af
.
format
,
error
))
return
AudioFormat
::
Undefined
();
return
format
;
return
af
;
}
void
ReplayGainFilter
::
Close
()
{
buffer
.
Clear
();
pv
.
Close
();
}
const
void
*
ReplayGainFilter
::
FilterPCM
(
const
void
*
src
,
size_t
src_size
,
size_t
*
dest_size_r
,
Error
&
error
)
size_t
*
dest_size_r
,
gcc_unused
Error
&
error
)
{
*
dest_size_r
=
src_size
;
if
(
volume
==
PCM_VOLUME_1
)
/* optimized special case: 100% volume = no-op */
return
src
;
void
*
dest
=
buffer
.
Get
(
src_size
);
if
(
volume
<=
0
)
{
/* optimized special case: 0% volume = memset(0) */
/* XXX is this valid for all sample formats? What
about floating point? */
memset
(
dest
,
0
,
src_size
);
return
dest
;
}
memcpy
(
dest
,
src
,
src_size
);
bool
success
=
pcm_volume
(
dest
,
src_size
,
format
.
format
,
volume
);
if
(
!
success
)
{
error
.
Set
(
replay_gain_domain
,
"pcm_volume() has failed"
);
return
nullptr
;
}
return
dest
;
const
auto
dest
=
pv
.
Apply
({
src
,
src_size
});
*
dest_size_r
=
dest
.
size
;
return
dest
.
data
;
}
const
struct
filter_plugin
replay_gain_filter_plugin
=
{
...
...
src/filter/VolumeFilterPlugin.cxx
View file @
8edde7a4
...
...
@@ -23,8 +23,8 @@
#include "FilterInternal.hxx"
#include "FilterRegistry.hxx"
#include "pcm/Volume.hxx"
#include "pcm/PcmBuffer.hxx"
#include "AudioFormat.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
...
...
@@ -32,29 +32,15 @@
#include <string.h>
class
VolumeFilter
final
:
public
Filter
{
/**
* The current volume, from 0 to #PCM_VOLUME_1.
*/
unsigned
volume
;
AudioFormat
format
;
PcmBuffer
buffer
;
PcmVolume
pv
;
public
:
VolumeFilter
()
:
volume
(
PCM_VOLUME_1
)
{}
unsigned
GetVolume
()
const
{
assert
(
volume
<=
PCM_VOLUME_1
);
return
volume
;
return
pv
.
GetVolume
();
}
void
SetVolume
(
unsigned
_volume
)
{
assert
(
_volume
<=
PCM_VOLUME_1
);
volume
=
_volume
;
pv
.
SetVolume
(
_volume
);
}
virtual
AudioFormat
Open
(
AudioFormat
&
af
,
Error
&
error
)
override
;
...
...
@@ -73,50 +59,27 @@ volume_filter_init(gcc_unused const config_param ¶m,
}
AudioFormat
VolumeFilter
::
Open
(
AudioFormat
&
audio_format
,
gcc_unused
Error
&
error
)
VolumeFilter
::
Open
(
AudioFormat
&
audio_format
,
Error
&
error
)
{
format
=
audio_format
;
if
(
!
pv
.
Open
(
audio_format
.
format
,
error
))
return
AudioFormat
::
Undefined
();
return
format
;
return
audio_
format
;
}
void
VolumeFilter
::
Close
()
{
buffer
.
Clear
();
pv
.
Close
();
}
const
void
*
VolumeFilter
::
FilterPCM
(
const
void
*
src
,
size_t
src_size
,
size_t
*
dest_size_r
,
Error
&
error
)
size_t
*
dest_size_r
,
gcc_unused
Error
&
error
)
{
*
dest_size_r
=
src_size
;
if
(
volume
>=
PCM_VOLUME_1
)
/* optimized special case: 100% volume = no-op */
return
src
;
void
*
dest
=
buffer
.
Get
(
src_size
);
if
(
volume
<=
0
)
{
/* optimized special case: 0% volume = memset(0) */
/* XXX is this valid for all sample formats? What
about floating point? */
memset
(
dest
,
0
,
src_size
);
return
dest
;
}
memcpy
(
dest
,
src
,
src_size
);
bool
success
=
pcm_volume
(
dest
,
src_size
,
format
.
format
,
volume
);
if
(
!
success
)
{
error
.
Set
(
volume_domain
,
"pcm_volume() has failed"
);
return
NULL
;
}
return
dest
;
const
auto
dest
=
pv
.
Apply
({
src
,
src_size
});
*
dest_size_r
=
dest
.
size
;
return
dest
.
data
;
}
const
struct
filter_plugin
volume_filter_plugin
=
{
...
...
src/pcm/Volume.cxx
View file @
8edde7a4
...
...
@@ -19,9 +19,11 @@
#include "config.h"
#include "Volume.hxx"
#include "Domain.hxx"
#include "PcmUtils.hxx"
#include "Traits.hxx"
#include "AudioFormat.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include <stdint.h>
#include <string.h>
...
...
@@ -143,61 +145,88 @@ pcm_volume_change_float(float *dest, const float *src, const float *end,
}
bool
pcm_volume
(
void
*
buffer
,
size_t
length
,
SampleFormat
format
,
int
volume
)
PcmVolume
::
Open
(
SampleFormat
_format
,
Error
&
error
)
{
if
(
volume
==
PCM_VOLUME_1S
)
return
true
;
assert
(
format
==
SampleFormat
::
UNDEFINED
);
if
(
volume
<=
0
)
{
memset
(
buffer
,
0
,
length
);
return
true
;
switch
(
_format
)
{
case
SampleFormat
:
:
UNDEFINED
:
case
SampleFormat
:
:
DSD
:
error
.
Format
(
pcm_domain
,
"Software volume for %s is not implemented"
,
sample_format_to_string
(
_format
));
return
false
;
case
SampleFormat
:
:
S8
:
case
SampleFormat
:
:
S16
:
case
SampleFormat
:
:
S24_P32
:
case
SampleFormat
:
:
S32
:
case
SampleFormat
:
:
FLOAT
:
break
;
}
const
void
*
end
=
pcm_end_pointer
(
buffer
,
length
);
format
=
_format
;
return
true
;
}
ConstBuffer
<
void
>
PcmVolume
::
Apply
(
ConstBuffer
<
void
>
src
)
{
if
(
volume
==
PCM_VOLUME_1
)
return
src
;
void
*
data
=
buffer
.
Get
(
src
.
size
);
if
(
volume
==
0
)
{
/* optimized special case: 0% volume = memset(0) */
/* TODO: is this valid for all sample formats? What
about floating point? */
memset
(
data
,
0
,
src
.
size
);
return
{
data
,
src
.
size
};
}
const
void
*
end
=
pcm_end_pointer
(
src
.
data
,
src
.
size
);
switch
(
format
)
{
case
SampleFormat
:
:
UNDEFINED
:
case
SampleFormat
:
:
DSD
:
/* not implemented */
return
false
;
assert
(
false
);
gcc_unreachable
()
;
case
SampleFormat
:
:
S8
:
pcm_volume_change_8
((
int8_t
*
)
buffer
,
(
const
int8_t
*
)
buffer
,
pcm_volume_change_8
((
int8_t
*
)
data
,
(
const
int8_t
*
)
src
.
data
,
(
const
int8_t
*
)
end
,
volume
);
return
true
;
break
;
case
SampleFormat
:
:
S16
:
pcm_volume_change_16
((
int16_t
*
)
buffer
,
(
const
int16_t
*
)
buffer
,
pcm_volume_change_16
((
int16_t
*
)
data
,
(
const
int16_t
*
)
src
.
data
,
(
const
int16_t
*
)
end
,
volume
);
return
true
;
break
;
case
SampleFormat
:
:
S24_P32
:
pcm_volume_change_24
((
int32_t
*
)
buffer
,
(
const
int32_t
*
)
buffer
,
pcm_volume_change_24
((
int32_t
*
)
data
,
(
const
int32_t
*
)
src
.
data
,
(
const
int32_t
*
)
end
,
volume
);
return
true
;
break
;
case
SampleFormat
:
:
S32
:
pcm_volume_change_32
((
int32_t
*
)
buffer
,
(
const
int32_t
*
)
buffer
,
pcm_volume_change_32
((
int32_t
*
)
data
,
(
const
int32_t
*
)
src
.
data
,
(
const
int32_t
*
)
end
,
volume
);
return
true
;
break
;
case
SampleFormat
:
:
FLOAT
:
pcm_volume_change_float
((
float
*
)
buffer
,
(
const
float
*
)
buffer
,
pcm_volume_change_float
((
float
*
)
data
,
(
const
float
*
)
src
.
data
,
(
const
float
*
)
end
,
pcm_volume_to_float
(
volume
));
return
true
;
break
;
}
assert
(
false
);
gcc_unreachable
();
return
{
data
,
src
.
size
};
}
src/pcm/Volume.hxx
View file @
8edde7a4
...
...
@@ -22,10 +22,18 @@
#include "PcmPrng.hxx"
#include "AudioFormat.hxx"
#include "PcmBuffer.hxx"
#include <stdint.h>
#include <stddef.h>
#ifndef NDEBUG
#include <assert.h>
#endif
class
Error
;
template
<
typename
T
>
struct
ConstBuffer
;
/**
* Number of fractional bits for a fixed-point volume value.
*/
...
...
@@ -71,17 +79,66 @@ pcm_volume_dither(void)
}
/**
* Adjust the volume of the specified PCM buffer.
*
* @param buffer the PCM buffer
* @param length the length of the PCM buffer
* @param format the sample format of the PCM buffer
* @param volume the volume between 0 and #PCM_VOLUME_1
* @return true on success, false if the audio format is not supported
* A class that converts samples from one format to another.
*/
bool
pcm_volume
(
void
*
buffer
,
size_t
length
,
SampleFormat
format
,
int
volume
);
class
PcmVolume
{
SampleFormat
format
;
unsigned
volume
;
PcmBuffer
buffer
;
public
:
PcmVolume
()
:
volume
(
PCM_VOLUME_1
)
{
#ifndef NDEBUG
format
=
SampleFormat
::
UNDEFINED
;
#endif
}
#ifndef NDEBUG
~
PcmVolume
()
{
assert
(
format
==
SampleFormat
::
UNDEFINED
);
}
#endif
unsigned
GetVolume
()
const
{
return
volume
;
}
/**
* @param _volume the volume level in the range
* [0..#PCM_VOLUME_1]; may be bigger than #PCM_VOLUME_1, but
* then it will most likely clip a lot
*/
void
SetVolume
(
unsigned
_volume
)
{
volume
=
_volume
;
}
/**
* Opens the object, prepare for Apply().
*
* @param format the sample format
* @param error location to store the error
* @return true on success
*/
bool
Open
(
SampleFormat
format
,
Error
&
error
);
/**
* Closes the object. After that, you may call Open() again.
*/
void
Close
()
{
#ifndef NDEBUG
assert
(
format
!=
SampleFormat
::
UNDEFINED
);
format
=
SampleFormat
::
UNDEFINED
;
#endif
}
/**
* Apply the volume level.
*/
gcc_pure
ConstBuffer
<
void
>
Apply
(
ConstBuffer
<
void
>
src
);
};
#endif
test/read_mixer.cxx
View file @
8edde7a4
...
...
@@ -101,15 +101,6 @@ filter_plugin_by_name(gcc_unused const char *name)
return
NULL
;
}
bool
pcm_volume
(
gcc_unused
void
*
buffer
,
gcc_unused
size_t
length
,
gcc_unused
SampleFormat
format
,
gcc_unused
int
volume
)
{
assert
(
false
);
return
false
;
}
int
main
(
int
argc
,
gcc_unused
char
**
argv
)
{
int
volume
;
...
...
test/software_volume.cxx
View file @
8edde7a4
...
...
@@ -27,12 +27,14 @@
#include "pcm/Volume.hxx"
#include "AudioParser.hxx"
#include "AudioFormat.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "stdbin.h"
#include <glib.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
int
main
(
int
argc
,
char
**
argv
)
...
...
@@ -55,14 +57,16 @@ int main(int argc, char **argv)
}
}
while
((
nbytes
=
read
(
0
,
buffer
,
sizeof
(
buffer
)))
>
0
)
{
if
(
!
pcm_volume
(
buffer
,
nbytes
,
audio_format
.
format
,
PCM_VOLUME_1
/
2
))
{
g_printerr
(
"pcm_volume() has failed
\n
"
);
return
2
;
}
PcmVolume
pv
;
if
(
!
pv
.
Open
(
audio_format
.
format
,
error
))
{
fprintf
(
stderr
,
"%s
\n
"
,
error
.
GetMessage
());
return
EXIT_FAILURE
;
}
gcc_unused
ssize_t
ignored
=
write
(
1
,
buffer
,
nbytes
);
while
((
nbytes
=
read
(
0
,
buffer
,
sizeof
(
buffer
)))
>
0
)
{
auto
dest
=
pv
.
Apply
({
buffer
,
size_t
(
nbytes
)});
gcc_unused
ssize_t
ignored
=
write
(
1
,
dest
.
data
,
dest
.
size
);
}
pv
.
Close
();
}
test/test_pcm_volume.cxx
View file @
8edde7a4
...
...
@@ -17,169 +17,108 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "test_pcm_all.hxx"
#include "pcm/Volume.hxx"
#include "pcm/Traits.hxx"
#include "util/ConstBuffer.hxx"
#include "util/Error.hxx"
#include "test_pcm_util.hxx"
#include <algorithm>
#include <string.h>
void
PcmVolumeTest
::
TestVolume8
()
template
<
SampleFormat
F
,
class
Traits
=
SampleTraits
<
F
>
,
typename
G
=
RandomInt
<
typename
Traits
::
value_type
>>
static
void
TestVolume
(
G
g
=
G
())
{
constexpr
unsigned
N
=
256
;
static
int8_t
zero
[
N
];
const
auto
src
=
TestDataBuffer
<
int8_t
,
N
>
();
typedef
typename
Traits
::
value_type
value_type
;
PcmVolume
pv
;
CPPUNIT_ASSERT
(
pv
.
Open
(
F
,
IgnoreError
()));
int8_t
dest
[
N
];
constexpr
size_t
N
=
256
;
static
value_type
zero
[
N
];
const
auto
_src
=
TestDataBuffer
<
value_type
,
N
>
(
g
);
const
ConstBuffer
<
void
>
src
(
_src
,
sizeof
(
_src
));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S8
,
0
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
zero
,
sizeof
(
zero
)));
pv
.
SetVolume
(
0
);
auto
dest
=
pv
.
Apply
(
src
);
CPPUNIT_ASSERT_EQUAL
(
src
.
size
,
dest
.
size
);
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
.
data
,
zero
,
sizeof
(
zero
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S8
,
PCM_VOLUME_1
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
src
,
sizeof
(
src
)));
pv
.
SetVolume
(
PCM_VOLUME_1
);
dest
=
pv
.
Apply
(
src
);
CPPUNIT_ASSERT_EQUAL
(
src
.
size
,
dest
.
size
);
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
.
data
,
src
.
data
,
src
.
size
));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S8
,
PCM_VOLUME_1
/
2
));
pv
.
SetVolume
(
PCM_VOLUME_1
/
2
);
dest
=
pv
.
Apply
(
src
);
CPPUNIT_ASSERT_EQUAL
(
src
.
size
,
dest
.
size
);
const
auto
_dest
=
ConstBuffer
<
value_type
>::
FromVoid
(
dest
);
for
(
unsigned
i
=
0
;
i
<
N
;
++
i
)
{
CPPUNIT_ASSERT
(
dest
[
i
]
>=
(
src
[
i
]
-
1
)
/
2
);
CPPUNIT_ASSERT
(
dest
[
i
]
<=
src
[
i
]
/
2
+
1
);
CPPUNIT_ASSERT
(
_dest
.
data
[
i
]
>=
(
_
src
[
i
]
-
1
)
/
2
);
CPPUNIT_ASSERT
(
_dest
.
data
[
i
]
<=
_
src
[
i
]
/
2
+
1
);
}
pv
.
Close
();
}
void
PcmVolumeTest
::
TestVolume
16
()
PcmVolumeTest
::
TestVolume
8
()
{
constexpr
unsigned
N
=
256
;
static
int16_t
zero
[
N
];
const
auto
src
=
TestDataBuffer
<
int16_t
,
N
>
();
int16_t
dest
[
N
];
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S16
,
0
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
zero
,
sizeof
(
zero
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S16
,
PCM_VOLUME_1
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
src
,
sizeof
(
src
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S16
,
PCM_VOLUME_1
/
2
));
TestVolume
<
SampleFormat
::
S8
>
();
}
for
(
unsigned
i
=
0
;
i
<
N
;
++
i
)
{
CPPUNIT_ASSERT
(
dest
[
i
]
>=
(
src
[
i
]
-
1
)
/
2
);
CPPUNIT_ASSERT
(
dest
[
i
]
<=
src
[
i
]
/
2
+
1
);
}
void
PcmVolumeTest
::
TestVolume16
()
{
TestVolume
<
SampleFormat
::
S16
>
();
}
void
PcmVolumeTest
::
TestVolume24
()
{
constexpr
unsigned
N
=
256
;
static
int32_t
zero
[
N
];
const
auto
src
=
TestDataBuffer
<
int32_t
,
N
>
(
RandomInt24
());
int32_t
dest
[
N
];
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S24_P32
,
0
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
zero
,
sizeof
(
zero
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S24_P32
,
PCM_VOLUME_1
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
src
,
sizeof
(
src
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S24_P32
,
PCM_VOLUME_1
/
2
));
for
(
unsigned
i
=
0
;
i
<
N
;
++
i
)
{
CPPUNIT_ASSERT
(
dest
[
i
]
>=
(
src
[
i
]
-
1
)
/
2
);
CPPUNIT_ASSERT
(
dest
[
i
]
<=
src
[
i
]
/
2
+
1
);
}
TestVolume
<
SampleFormat
::
S24_P32
>
(
RandomInt24
());
}
void
PcmVolumeTest
::
TestVolume32
()
{
constexpr
unsigned
N
=
256
;
static
int32_t
zero
[
N
];
const
auto
src
=
TestDataBuffer
<
int32_t
,
N
>
();
int32_t
dest
[
N
];
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S32
,
0
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
zero
,
sizeof
(
zero
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S32
,
PCM_VOLUME_1
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
src
,
sizeof
(
src
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
S32
,
PCM_VOLUME_1
/
2
));
for
(
unsigned
i
=
0
;
i
<
N
;
++
i
)
{
CPPUNIT_ASSERT
(
dest
[
i
]
>=
(
src
[
i
]
-
1
)
/
2
);
CPPUNIT_ASSERT
(
dest
[
i
]
<=
src
[
i
]
/
2
+
1
);
}
TestVolume
<
SampleFormat
::
S32
>
();
}
void
PcmVolumeTest
::
TestVolumeFloat
()
{
constexpr
unsigned
N
=
256
;
static
float
zero
[
N
];
const
auto
src
=
TestDataBuffer
<
float
,
N
>
(
RandomFloat
());
PcmVolume
pv
;
CPPUNIT_ASSERT
(
pv
.
Open
(
SampleFormat
::
FLOAT
,
IgnoreError
()));
float
dest
[
N
];
constexpr
size_t
N
=
256
;
static
float
zero
[
N
];
const
auto
_src
=
TestDataBuffer
<
float
,
N
>
(
RandomFloat
());
const
ConstBuffer
<
void
>
src
(
_src
,
sizeof
(
_src
));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
FLOAT
,
0
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
zero
,
sizeof
(
zero
)));
pv
.
SetVolume
(
0
);
auto
dest
=
pv
.
Apply
(
src
);
CPPUNIT_ASSERT_EQUAL
(
src
.
size
,
dest
.
size
);
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
.
data
,
zero
,
sizeof
(
zero
)));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
FLOAT
,
PCM_VOLUME_1
));
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
,
src
,
sizeof
(
src
)));
pv
.
SetVolume
(
PCM_VOLUME_1
);
dest
=
pv
.
Apply
(
src
);
CPPUNIT_ASSERT_EQUAL
(
src
.
size
,
dest
.
size
);
CPPUNIT_ASSERT_EQUAL
(
0
,
memcmp
(
dest
.
data
,
src
.
data
,
src
.
size
));
std
::
copy
(
src
.
begin
(),
src
.
end
(),
dest
);
CPPUNIT_ASSERT_EQUAL
(
true
,
pcm_volume
(
dest
,
sizeof
(
dest
),
SampleFormat
::
FLOAT
,
PCM_VOLUME_1
/
2
));
pv
.
SetVolume
(
PCM_VOLUME_1
/
2
);
dest
=
pv
.
Apply
(
src
);
CPPUNIT_ASSERT_EQUAL
(
src
.
size
,
dest
.
size
);
const
auto
_dest
=
ConstBuffer
<
float
>::
FromVoid
(
dest
);
for
(
unsigned
i
=
0
;
i
<
N
;
++
i
)
CPPUNIT_ASSERT_DOUBLES_EQUAL
(
src
[
i
]
/
2
,
dest
[
i
],
1
);
CPPUNIT_ASSERT_DOUBLES_EQUAL
(
_src
[
i
]
/
2
,
_dest
.
data
[
i
],
1
);
pv
.
Close
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment