@@ -30,12 +30,13 @@ struct sndfile_type_info {
30
30
31
31
struct sndfile_enc_info {
32
32
const char * name ;
33
- int prec , can_dither , sf_enc ;
33
+ int prec , can_dither , do_scale , sf_enc ;
34
34
};
35
35
36
36
struct sndfile_state {
37
37
SNDFILE * f ;
38
38
SF_INFO * info ;
39
+ sample_t scale ;
39
40
};
40
41
41
42
static const char codec_name [] = "sndfile" ;
@@ -71,39 +72,39 @@ static struct sndfile_type_info types[] = {
71
72
};
72
73
73
74
static struct sndfile_enc_info encodings [] = {
74
- { "s16" , 16 , 1 , SF_FORMAT_PCM_16 },
75
- { "s8" , 8 , 1 , SF_FORMAT_PCM_S8 },
76
- { "u8" , 8 , 1 , SF_FORMAT_PCM_U8 },
77
- { "s24" , 24 , 1 , SF_FORMAT_PCM_24 },
78
- { "s32" , 32 , 1 , SF_FORMAT_PCM_32 },
79
- { "float" , 24 , 0 , SF_FORMAT_FLOAT },
80
- { "double" , 53 , 0 , SF_FORMAT_DOUBLE },
81
- { "mu-law" , 13 , 0 , SF_FORMAT_ULAW },
82
- { "a-law" , 14 , 0 , SF_FORMAT_ALAW },
83
- { "ima_adpcm" , 13 , 0 , SF_FORMAT_IMA_ADPCM },
84
- { "ms_adpcm" , 13 , 0 , SF_FORMAT_MS_ADPCM },
85
- { "gsm6.10" , 16 , 0 , SF_FORMAT_GSM610 },
86
- { "vox_adpcm" , 13 , 0 , SF_FORMAT_VOX_ADPCM },
87
- { "nms_adpcm_16" , 8 , 0 , SF_FORMAT_NMS_ADPCM_16 },
88
- { "nms_adpcm_24" , 8 , 0 , SF_FORMAT_NMS_ADPCM_24 },
89
- { "nms_adpcm_32" , 12 , 0 , SF_FORMAT_NMS_ADPCM_32 },
90
- { "g721_32" , 12 , 0 , SF_FORMAT_G721_32 },
91
- { "g723_24" , 8 , 0 , SF_FORMAT_G723_24 },
92
- { "g723_40" , 14 , 0 , SF_FORMAT_G723_40 },
93
- { "dwvw_12" , 12 , 0 , SF_FORMAT_DWVW_12 },
94
- { "dwvw_16" , 16 , 0 , SF_FORMAT_DWVW_16 },
95
- { "dwvw_24" , 24 , 0 , SF_FORMAT_DWVW_24 },
96
- { "dpcm_8" , 8 , 0 , SF_FORMAT_DPCM_8 },
97
- { "dpcm_16" , 16 , 0 , SF_FORMAT_DPCM_16 },
98
- { "vorbis" , 24 , 0 , SF_FORMAT_VORBIS },
99
- { "opus" , 24 , 0 , SF_FORMAT_OPUS },
100
- { "alac_16" , 16 , 1 , SF_FORMAT_ALAC_16 },
101
- { "alac_20" , 20 , 1 , SF_FORMAT_ALAC_20 },
102
- { "alac_24" , 24 , 1 , SF_FORMAT_ALAC_24 },
103
- { "alac_32" , 32 , 1 , SF_FORMAT_ALAC_32 },
104
- { "mpeg1.1" , 24 , 0 , SF_FORMAT_MPEG_LAYER_I },
105
- { "mpeg1.2" , 24 , 0 , SF_FORMAT_MPEG_LAYER_II },
106
- { "mpeg2.3" , 24 , 0 , SF_FORMAT_MPEG_LAYER_III },
75
+ { "s16" , 16 , 1 , 1 , SF_FORMAT_PCM_16 },
76
+ { "s8" , 8 , 1 , 1 , SF_FORMAT_PCM_S8 },
77
+ { "u8" , 8 , 1 , 1 , SF_FORMAT_PCM_U8 },
78
+ { "s24" , 24 , 1 , 1 , SF_FORMAT_PCM_24 },
79
+ { "s32" , 32 , 1 , 1 , SF_FORMAT_PCM_32 },
80
+ { "float" , 24 , 0 , 0 , SF_FORMAT_FLOAT },
81
+ { "double" , 53 , 0 , 0 , SF_FORMAT_DOUBLE },
82
+ { "mu-law" , 13 , 0 , 0 , SF_FORMAT_ULAW },
83
+ { "a-law" , 14 , 0 , 0 , SF_FORMAT_ALAW },
84
+ { "ima_adpcm" , 13 , 0 , 0 , SF_FORMAT_IMA_ADPCM },
85
+ { "ms_adpcm" , 13 , 0 , 0 , SF_FORMAT_MS_ADPCM },
86
+ { "gsm6.10" , 16 , 0 , 0 , SF_FORMAT_GSM610 },
87
+ { "vox_adpcm" , 13 , 0 , 0 , SF_FORMAT_VOX_ADPCM },
88
+ { "nms_adpcm_16" , 8 , 0 , 0 , SF_FORMAT_NMS_ADPCM_16 },
89
+ { "nms_adpcm_24" , 8 , 0 , 0 , SF_FORMAT_NMS_ADPCM_24 },
90
+ { "nms_adpcm_32" , 12 , 0 , 0 , SF_FORMAT_NMS_ADPCM_32 },
91
+ { "g721_32" , 12 , 0 , 0 , SF_FORMAT_G721_32 },
92
+ { "g723_24" , 8 , 0 , 0 , SF_FORMAT_G723_24 },
93
+ { "g723_40" , 14 , 0 , 0 , SF_FORMAT_G723_40 },
94
+ { "dwvw_12" , 12 , 0 , 0 , SF_FORMAT_DWVW_12 },
95
+ { "dwvw_16" , 16 , 0 , 0 , SF_FORMAT_DWVW_16 },
96
+ { "dwvw_24" , 24 , 0 , 0 , SF_FORMAT_DWVW_24 },
97
+ { "dpcm_8" , 8 , 0 , 0 , SF_FORMAT_DPCM_8 },
98
+ { "dpcm_16" , 16 , 0 , 0 , SF_FORMAT_DPCM_16 },
99
+ { "vorbis" , 24 , 0 , 0 , SF_FORMAT_VORBIS },
100
+ { "opus" , 24 , 0 , 0 , SF_FORMAT_OPUS },
101
+ { "alac_16" , 16 , 1 , 0 , SF_FORMAT_ALAC_16 },
102
+ { "alac_20" , 20 , 1 , 0 , SF_FORMAT_ALAC_20 },
103
+ { "alac_24" , 24 , 1 , 0 , SF_FORMAT_ALAC_24 },
104
+ { "alac_32" , 32 , 1 , 0 , SF_FORMAT_ALAC_32 },
105
+ { "mpeg1.1" , 24 , 0 , 0 , SF_FORMAT_MPEG_LAYER_I },
106
+ { "mpeg1.2" , 24 , 0 , 0 , SF_FORMAT_MPEG_LAYER_II },
107
+ { "mpeg2.3" , 24 , 0 , 0 , SF_FORMAT_MPEG_LAYER_III },
107
108
};
108
109
109
110
ssize_t sndfile_read (struct codec * c , sample_t * buf , ssize_t frames )
@@ -116,10 +117,20 @@ ssize_t sndfile_read(struct codec *c, sample_t *buf, ssize_t frames)
116
117
return (ssize_t ) r ;
117
118
}
118
119
120
+ static inline void buf_scale_int (sample_t * buf , const sample_t s , ssize_t samples )
121
+ {
122
+ const sample_t c = s - 1.0 ;
123
+ for (sample_t * end = buf + samples ; buf < end ; ++ buf ) {
124
+ * buf *= s ;
125
+ if (* buf > c ) * buf = c ;
126
+ }
127
+ }
128
+
119
129
ssize_t sndfile_write (struct codec * c , sample_t * buf , ssize_t frames )
120
130
{
121
131
int e = 0 ;
122
132
struct sndfile_state * state = (struct sndfile_state * ) c -> data ;
133
+ if (state -> scale > 1.0 ) buf_scale_int (buf , state -> scale , frames * c -> channels );
123
134
const sf_count_t r = sf_writef_double (state -> f , buf , frames );
124
135
if (r != frames && (e = sf_error (state -> f )) != SF_ERR_NO_ERROR )
125
136
LOG_FMT (LL_ERROR , "%s: %s" , __func__ , sf_error_number (e ));
@@ -239,16 +250,18 @@ struct codec * sndfile_codec_init(const struct codec_params *p)
239
250
goto fail ;
240
251
}
241
252
242
- #if BIT_PERFECT && 0 /* libsndfile's sample type conversion is broken... */
243
- sf_command (f , SFC_SET_CLIPPING , NULL , SF_TRUE );
244
- #endif
245
-
253
+ enc_info = sndfile_get_enc_info (info -> format );
246
254
state = calloc (1 , sizeof (struct sndfile_state ));
247
255
state -> f = f ;
248
256
state -> info = info ;
257
+ #if BIT_PERFECT
258
+ if (p -> mode == CODEC_MODE_WRITE && enc_info -> do_scale ) {
259
+ state -> scale = (sample_t ) (((uint32_t ) 1 ) << (enc_info -> prec - 1 ));
260
+ sf_command (f , SFC_SET_NORM_DOUBLE , NULL , SF_FALSE );
261
+ }
262
+ #endif
249
263
250
264
c = calloc (1 , sizeof (struct codec ));
251
- enc_info = sndfile_get_enc_info (info -> format );
252
265
c -> path = p -> path ;
253
266
c -> type = sndfile_get_type_name (info -> format );
254
267
c -> enc = (enc_info ) ? enc_info -> name : "unknown" ;
0 commit comments