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
1abfcc56
Commit
1abfcc56
authored
Jan 15, 2010
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
audio_format: support packed 24 bit samples
parent
da47afe7
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
278 additions
and
1 deletion
+278
-1
Makefile.am
Makefile.am
+3
-0
NEWS
NEWS
+1
-0
user.xml
doc/user.xml
+11
-0
audio_format.c
src/audio_format.c
+3
-0
audio_format.h
src/audio_format.h
+9
-0
audio_parser.c
src/audio_parser.c
+6
-1
flac_pcm.c
src/decoder/flac_pcm.c
+1
-0
pcm_convert.c
src/pcm_convert.c
+48
-0
pcm_convert.h
src/pcm_convert.h
+3
-0
pcm_format.c
src/pcm_format.c
+41
-0
pcm_pack.c
src/pcm_pack.c
+93
-0
pcm_pack.h
src/pcm_pack.h
+59
-0
No files found.
Makefile.am
View file @
1abfcc56
...
...
@@ -279,6 +279,7 @@ src_mpd_SOURCES = \
src/pcm_mix.c
\
src/pcm_byteswap.c
\
src/pcm_channels.c
\
src/pcm_pack.c
\
src/pcm_format.c
\
src/pcm_resample.c
\
src/pcm_resample_fallback.c
\
...
...
@@ -888,6 +889,7 @@ test_run_filter_SOURCES = test/run_filter.c \
src/conf.c src/tokenizer.c src/utils.c
\
src/pcm_volume.c src/pcm_convert.c src/pcm_byteswap.c
\
src/pcm_format.c src/pcm_channels.c src/pcm_dither.c
\
src/pcm_pack.c
\
src/pcm_resample.c src/pcm_resample_fallback.c
\
src/audio_check.c
\
src/audio_format.c
\
...
...
@@ -935,6 +937,7 @@ test_run_convert_SOURCES = test/run_convert.c \
src/audio_parser.c
\
src/pcm_channels.c
\
src/pcm_format.c
\
src/pcm_pack.c
\
src/pcm_dither.c
\
src/pcm_byteswap.c
\
src/pcm_resample.c
\
...
...
NEWS
View file @
1abfcc56
...
...
@@ -78,6 +78,7 @@ ver 0.16 (20??/??/??)
* log: redirect stdout/stderr to /dev/null if syslog is used
* set the close-on-exec flag on all file descriptors
* pcm_volume, pcm_mix: implemented 32 bit support
* support packed 24 bit samples
* CUE sheet support
* obey $(sysconfdir) for default mpd.conf location
* build with large file support by default
...
...
doc/user.xml
View file @
1abfcc56
...
...
@@ -313,6 +313,17 @@ cd mpd-version</programlisting>
<parameter>
*:*:*
</parameter>
is equal to not having
a
<varname>
format
</varname>
specification.
</para>
<para>
The following values are valid for
<varname>
bits
</varname>
:
<varname>
8
</varname>
(signed 8 bit integer samples),
<varname>
16
</varname>
,
<varname>
24
</varname>
(signed
24 bit integer samples padded to 32 bit),
<varname>
24_3
</varname>
(signed 24 bit integer
samples, no padding, 3 bytes per sample),
<varname>
32
</varname>
(signed 32 bit integer
samples).
</para>
</entry>
</row>
<row>
...
...
src/audio_format.c
View file @
1abfcc56
...
...
@@ -41,6 +41,9 @@ sample_format_to_string(enum sample_format format)
case
SAMPLE_FORMAT_S16
:
return
"16"
;
case
SAMPLE_FORMAT_S24
:
return
"24_3"
;
case
SAMPLE_FORMAT_S24_P32
:
return
"24"
;
...
...
src/audio_format.h
View file @
1abfcc56
...
...
@@ -30,6 +30,11 @@ enum sample_format {
SAMPLE_FORMAT_S16
,
/**
* Signed 24 bit integer samples, without padding.
*/
SAMPLE_FORMAT_S24
,
/**
* Signed 24 bit integer samples, packed in 32 bit integers
* (the most significant byte is filled with the sign bit).
*/
...
...
@@ -156,6 +161,7 @@ audio_valid_sample_format(enum sample_format format)
switch
(
format
)
{
case
SAMPLE_FORMAT_S8
:
case
SAMPLE_FORMAT_S16
:
case
SAMPLE_FORMAT_S24
:
case
SAMPLE_FORMAT_S24_P32
:
case
SAMPLE_FORMAT_S32
:
return
true
;
...
...
@@ -235,6 +241,9 @@ static inline unsigned audio_format_sample_size(const struct audio_format *af)
case
SAMPLE_FORMAT_S16
:
return
2
;
case
SAMPLE_FORMAT_S24
:
return
3
;
case
SAMPLE_FORMAT_S24_P32
:
case
SAMPLE_FORMAT_S32
:
return
4
;
...
...
src/audio_parser.c
View file @
1abfcc56
...
...
@@ -28,6 +28,7 @@
#include "audio_check.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/**
...
...
@@ -97,7 +98,11 @@ parse_sample_format(const char *src, bool mask,
break
;
case
24
:
sample_format
=
SAMPLE_FORMAT_S24_P32
;
if
(
memcmp
(
endptr
,
"_3"
,
2
)
==
0
)
{
sample_format
=
SAMPLE_FORMAT_S24
;
endptr
+=
2
;
}
else
sample_format
=
SAMPLE_FORMAT_S24_P32
;
break
;
case
32
:
...
...
src/decoder/flac_pcm.c
View file @
1abfcc56
...
...
@@ -101,6 +101,7 @@ flac_convert(void *dest,
position
,
end
);
break
;
case
SAMPLE_FORMAT_S24
:
case
SAMPLE_FORMAT_UNDEFINED
:
/* unreachable */
assert
(
false
);
...
...
src/pcm_convert.c
View file @
1abfcc56
...
...
@@ -22,6 +22,7 @@
#include "pcm_channels.h"
#include "pcm_format.h"
#include "pcm_byteswap.h"
#include "pcm_pack.h"
#include "audio_format.h"
#include <assert.h>
...
...
@@ -40,6 +41,7 @@ void pcm_convert_init(struct pcm_convert_state *state)
pcm_dither_24_init
(
&
state
->
dither
);
pcm_buffer_init
(
&
state
->
format_buffer
);
pcm_buffer_init
(
&
state
->
pack_buffer
);
pcm_buffer_init
(
&
state
->
channels_buffer
);
pcm_buffer_init
(
&
state
->
byteswap_buffer
);
}
...
...
@@ -49,6 +51,7 @@ void pcm_convert_deinit(struct pcm_convert_state *state)
pcm_resample_deinit
(
&
state
->
resample
);
pcm_buffer_deinit
(
&
state
->
format_buffer
);
pcm_buffer_deinit
(
&
state
->
pack_buffer
);
pcm_buffer_deinit
(
&
state
->
channels_buffer
);
pcm_buffer_deinit
(
&
state
->
byteswap_buffer
);
}
...
...
@@ -164,6 +167,45 @@ pcm_convert_24(struct pcm_convert_state *state,
return
buf
;
}
/**
* Convert to 24 bit packed samples (aka S24_3LE / S24_3BE).
*/
static
const
void
*
pcm_convert_24_packed
(
struct
pcm_convert_state
*
state
,
const
struct
audio_format
*
src_format
,
const
void
*
src_buffer
,
size_t
src_size
,
const
struct
audio_format
*
dest_format
,
size_t
*
dest_size_r
,
GError
**
error_r
)
{
assert
(
dest_format
->
format
==
SAMPLE_FORMAT_S24
);
/* use the normal 24 bit conversion first */
struct
audio_format
audio_format
;
audio_format_init
(
&
audio_format
,
dest_format
->
sample_rate
,
SAMPLE_FORMAT_S24_P32
,
dest_format
->
channels
);
const
int32_t
*
buffer
;
size_t
buffer_size
;
buffer
=
pcm_convert_24
(
state
,
src_format
,
src_buffer
,
src_size
,
&
audio_format
,
&
buffer_size
,
error_r
);
if
(
buffer
==
NULL
)
return
NULL
;
/* now convert to packed 24 bit */
unsigned
num_samples
=
buffer_size
/
4
;
size_t
dest_size
=
num_samples
*
3
;
uint8_t
*
dest
=
pcm_buffer_get
(
&
state
->
pack_buffer
,
dest_size
);
pcm_pack_24
(
dest
,
buffer
,
num_samples
,
dest_format
->
reverse_endian
);
*
dest_size_r
=
dest_size
;
return
dest
;
}
static
const
int32_t
*
pcm_convert_32
(
struct
pcm_convert_state
*
state
,
const
struct
audio_format
*
src_format
,
...
...
@@ -234,6 +276,12 @@ pcm_convert(struct pcm_convert_state *state,
dest_format
,
dest_size_r
,
error_r
);
case
SAMPLE_FORMAT_S24
:
return
pcm_convert_24_packed
(
state
,
src_format
,
src
,
src_size
,
dest_format
,
dest_size_r
,
error_r
);
case
SAMPLE_FORMAT_S24_P32
:
return
pcm_convert_24
(
state
,
src_format
,
src
,
src_size
,
...
...
src/pcm_convert.h
View file @
1abfcc56
...
...
@@ -39,6 +39,9 @@ struct pcm_convert_state {
/** the buffer for converting the sample format */
struct
pcm_buffer
format_buffer
;
/** the buffer for converting to/from packed samples */
struct
pcm_buffer
pack_buffer
;
/** the buffer for converting the channel count */
struct
pcm_buffer
channels_buffer
;
...
...
src/pcm_format.c
View file @
1abfcc56
...
...
@@ -21,6 +21,7 @@
#include "pcm_format.h"
#include "pcm_dither.h"
#include "pcm_buffer.h"
#include "pcm_pack.h"
static
void
pcm_convert_8_to_16
(
int16_t
*
out
,
const
int8_t
*
in
,
...
...
@@ -48,6 +49,15 @@ pcm_convert_32_to_16(struct pcm_dither *dither,
pcm_dither_32_to_16
(
dither
,
out
,
in
,
num_samples
);
}
static
int32_t
*
pcm_convert_24_to_24p32
(
struct
pcm_buffer
*
buffer
,
const
uint8_t
*
src
,
unsigned
num_samples
)
{
int32_t
*
dest
=
pcm_buffer_get
(
buffer
,
num_samples
*
4
);
pcm_unpack_24
(
dest
,
src
,
num_samples
,
false
);
return
dest
;
}
const
int16_t
*
pcm_convert_to_16
(
struct
pcm_buffer
*
buffer
,
struct
pcm_dither
*
dither
,
enum
sample_format
src_format
,
const
void
*
src
,
...
...
@@ -55,6 +65,7 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
{
unsigned
num_samples
;
int16_t
*
dest
;
int32_t
*
dest32
;
switch
(
src_format
)
{
case
SAMPLE_FORMAT_UNDEFINED
:
...
...
@@ -74,6 +85,19 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
*
dest_size_r
=
src_size
;
return
src
;
case
SAMPLE_FORMAT_S24
:
/* convert to S24_P32 first */
num_samples
=
src_size
/
3
;
dest32
=
pcm_convert_24_to_24p32
(
buffer
,
src
,
num_samples
);
dest
=
(
int16_t
*
)
dest32
;
/* convert to 16 bit in-place */
*
dest_size_r
=
num_samples
*
sizeof
(
*
dest
);
pcm_convert_24_to_16
(
dither
,
dest
,
dest32
,
num_samples
);
return
dest
;
case
SAMPLE_FORMAT_S24_P32
:
num_samples
=
src_size
/
4
;
*
dest_size_r
=
num_samples
*
sizeof
(
*
dest
);
...
...
@@ -158,6 +182,12 @@ pcm_convert_to_24(struct pcm_buffer *buffer,
num_samples
);
return
dest
;
case
SAMPLE_FORMAT_S24
:
num_samples
=
src_size
/
3
;
*
dest_size_r
=
num_samples
*
sizeof
(
*
dest
);
return
pcm_convert_24_to_24p32
(
buffer
,
src
,
num_samples
);
case
SAMPLE_FORMAT_S24_P32
:
*
dest_size_r
=
src_size
;
return
src
;
...
...
@@ -235,6 +265,17 @@ pcm_convert_to_32(struct pcm_buffer *buffer,
num_samples
);
return
dest
;
case
SAMPLE_FORMAT_S24
:
/* convert to S24_P32 first */
num_samples
=
src_size
/
3
;
dest
=
pcm_convert_24_to_24p32
(
buffer
,
src
,
num_samples
);
/* convert to 32 bit in-place */
*
dest_size_r
=
num_samples
*
sizeof
(
*
dest
);
pcm_convert_24_to_32
(
dest
,
dest
,
num_samples
);
return
dest
;
case
SAMPLE_FORMAT_S24_P32
:
num_samples
=
src_size
/
4
;
*
dest_size_r
=
num_samples
*
sizeof
(
*
dest
);
...
...
src/pcm_pack.c
0 → 100644
View file @
1abfcc56
/*
* Copyright (C) 2003-2010 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "pcm_pack.h"
#include <glib.h>
static
void
pack_sample
(
uint8_t
*
dest
,
const
int32_t
*
src0
,
bool
reverse_endian
)
{
const
uint8_t
*
src
=
(
const
uint8_t
*
)
src0
;
if
((
G_BYTE_ORDER
==
G_BIG_ENDIAN
)
!=
reverse_endian
)
++
src
;
*
dest
++
=
*
src
++
;
*
dest
++
=
*
src
++
;
*
dest
++
=
*
src
++
;
}
void
pcm_pack_24
(
uint8_t
*
dest
,
const
int32_t
*
src
,
unsigned
num_samples
,
bool
reverse_endian
)
{
/* duplicate loop to help the compiler's optimizer (constant
parameter to the pack_sample() inline function) */
if
(
G_LIKELY
(
!
reverse_endian
))
{
while
(
num_samples
--
>
0
)
{
pack_sample
(
dest
,
src
++
,
false
);
dest
+=
3
;
}
}
else
{
while
(
num_samples
--
>
0
)
{
pack_sample
(
dest
,
src
++
,
true
);
dest
+=
3
;
}
}
}
static
void
unpack_sample
(
int32_t
*
dest0
,
const
uint8_t
*
src
,
bool
reverse_endian
)
{
uint8_t
*
dest
=
(
uint8_t
*
)
dest0
;
if
((
G_BYTE_ORDER
==
G_BIG_ENDIAN
)
!=
reverse_endian
)
/* extend the sign bit to the most fourth byte */
*
dest
++
=
*
src
&
0x80
?
0xff
:
0x00
;
*
dest
++
=
*
src
++
;
*
dest
++
=
*
src
++
;
*
dest
++
=
*
src
;
if
((
G_BYTE_ORDER
==
G_LITTLE_ENDIAN
)
!=
reverse_endian
)
/* extend the sign bit to the most fourth byte */
*
dest
++
=
*
src
&
0x80
?
0xff
:
0x00
;
}
void
pcm_unpack_24
(
int32_t
*
dest
,
const
uint8_t
*
src
,
unsigned
num_samples
,
bool
reverse_endian
)
{
/* duplicate loop to help the compiler's optimizer (constant
parameter to the unpack_sample() inline function) */
if
(
G_LIKELY
(
!
reverse_endian
))
{
while
(
num_samples
--
>
0
)
{
unpack_sample
(
dest
++
,
src
,
false
);
src
+=
3
;
}
}
else
{
while
(
num_samples
--
>
0
)
{
unpack_sample
(
dest
++
,
src
,
true
);
src
+=
3
;
}
}
}
src/pcm_pack.h
0 → 100644
View file @
1abfcc56
/*
* Copyright (C) 2003-2010 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/** \file
*
* Library for working with packed 24 bit samples.
*/
#ifndef PCM_PACK_H
#define PCM_PACK_H
#include <stdbool.h>
#include <stdint.h>
/**
* Converts padded 24 bit samples (4 bytes per sample) to packed 24
* bit samples (3 bytes per sample).
*
* This function can be used to convert a buffer in-place.
*
* @param dest the destination buffer (array of triples)
* @param src the source buffer
* @param num_samples the number of samples to convert
* @param reverse_endian is src and dest in non-host byte order?
*/
void
pcm_pack_24
(
uint8_t
*
dest
,
const
int32_t
*
src
,
unsigned
num_samples
,
bool
reverse_endian
);
/**
* Converts packed 24 bit samples (3 bytes per sample) to padded 24
* bit samples (4 bytes per sample).
*
* @param dest the destination buffer
* @param src the source buffer (array of triples)
* @param num_samples the number of samples to convert
* @param reverse_endian is src and dest in non-host byte order?
*/
void
pcm_unpack_24
(
int32_t
*
dest
,
const
uint8_t
*
src
,
unsigned
num_samples
,
bool
reverse_endian
);
#endif
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