1b815c7f3Sopenharmony_ci/* 2b815c7f3Sopenharmony_ci** Copyright (C) 2020 Arthur Taylor <art@ified.ca> 3b815c7f3Sopenharmony_ci** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com> 4b815c7f3Sopenharmony_ci** 5b815c7f3Sopenharmony_ci** This program is free software ; you can redistribute it and/or modify 6b815c7f3Sopenharmony_ci** it under the terms of the GNU Lesser General Public License as published by 7b815c7f3Sopenharmony_ci** the Free Software Foundation ; either version 2.1 of the License, or 8b815c7f3Sopenharmony_ci** (at your option) any later version. 9b815c7f3Sopenharmony_ci** 10b815c7f3Sopenharmony_ci** This program is distributed in the hope that it will be useful, 11b815c7f3Sopenharmony_ci** but WITHOUT ANY WARRANTY ; without even the implied warranty of 12b815c7f3Sopenharmony_ci** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13b815c7f3Sopenharmony_ci** GNU Lesser General Public License for more details. 14b815c7f3Sopenharmony_ci** 15b815c7f3Sopenharmony_ci** You should have received a copy of the GNU Lesser General Public License 16b815c7f3Sopenharmony_ci** along with this program ; if not, write to the Free Software 17b815c7f3Sopenharmony_ci** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18b815c7f3Sopenharmony_ci*/ 19b815c7f3Sopenharmony_ci 20b815c7f3Sopenharmony_ci#include "sfconfig.h" 21b815c7f3Sopenharmony_ci#include "sndfile.h" 22b815c7f3Sopenharmony_ci#include "common.h" 23b815c7f3Sopenharmony_ci#include "mpeg.h" 24b815c7f3Sopenharmony_ci 25b815c7f3Sopenharmony_ci 26b815c7f3Sopenharmony_ci#if HAVE_MPEG 27b815c7f3Sopenharmony_ci 28b815c7f3Sopenharmony_ci#include <lame/lame.h> 29b815c7f3Sopenharmony_ci 30b815c7f3Sopenharmony_ci/* 31b815c7f3Sopenharmony_ci * RANT RANT RANT 32b815c7f3Sopenharmony_ci * 33b815c7f3Sopenharmony_ci * Lame has 11 functions for inputing sample data of various types and 34b815c7f3Sopenharmony_ci * configurations, but due to bad definitions, or missing combinations, they 35b815c7f3Sopenharmony_ci * aren't really of much help to us. 36b815c7f3Sopenharmony_ci * 37b815c7f3Sopenharmony_ci */ 38b815c7f3Sopenharmony_ci 39b815c7f3Sopenharmony_citypedef struct 40b815c7f3Sopenharmony_ci{ lame_t lamef ; 41b815c7f3Sopenharmony_ci unsigned char *block ; 42b815c7f3Sopenharmony_ci size_t block_len ; 43b815c7f3Sopenharmony_ci int frame_samples ; 44b815c7f3Sopenharmony_ci double compression ; 45b815c7f3Sopenharmony_ci int initialized ; 46b815c7f3Sopenharmony_ci} MPEG_L3_ENC_PRIVATE ; 47b815c7f3Sopenharmony_ci 48b815c7f3Sopenharmony_ci 49b815c7f3Sopenharmony_ci/*----------------------------------------------------------------------------------------------- 50b815c7f3Sopenharmony_ci** Private function prototypes. 51b815c7f3Sopenharmony_ci*/ 52b815c7f3Sopenharmony_ci 53b815c7f3Sopenharmony_cistatic int mpeg_l3_encoder_close (SF_PRIVATE *psf) ; 54b815c7f3Sopenharmony_cistatic int mpeg_l3_encoder_construct (SF_PRIVATE *psf) ; 55b815c7f3Sopenharmony_cistatic int mpeg_l3_encoder_byterate (SF_PRIVATE *psf) ; 56b815c7f3Sopenharmony_ci 57b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_short_stereo (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; 58b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_int_stereo (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; 59b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; 60b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_double_stereo (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; 61b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_short_mono (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; 62b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_int_mono (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; 63b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; 64b815c7f3Sopenharmony_cistatic sf_count_t mpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; 65b815c7f3Sopenharmony_ci 66b815c7f3Sopenharmony_ci/*----------------------------------------------------------------------------------------------- 67b815c7f3Sopenharmony_ci** Exported functions. 68b815c7f3Sopenharmony_ci*/ 69b815c7f3Sopenharmony_ci 70b815c7f3Sopenharmony_ciint 71b815c7f3Sopenharmony_cimpeg_l3_encoder_init (SF_PRIVATE *psf, int info_tag) 72b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE* pmpeg = NULL ; 73b815c7f3Sopenharmony_ci 74b815c7f3Sopenharmony_ci if (psf->file.mode == SFM_RDWR) 75b815c7f3Sopenharmony_ci return SFE_BAD_MODE_RW ; 76b815c7f3Sopenharmony_ci 77b815c7f3Sopenharmony_ci if (psf->file.mode != SFM_WRITE) 78b815c7f3Sopenharmony_ci return SFE_INTERNAL ; 79b815c7f3Sopenharmony_ci 80b815c7f3Sopenharmony_ci psf->codec_data = pmpeg = calloc (1, sizeof (MPEG_L3_ENC_PRIVATE)) ; 81b815c7f3Sopenharmony_ci if (!pmpeg) 82b815c7f3Sopenharmony_ci return SFE_MALLOC_FAILED ; 83b815c7f3Sopenharmony_ci 84b815c7f3Sopenharmony_ci if (psf->sf.channels < 1 || psf->sf.channels > 2) 85b815c7f3Sopenharmony_ci return SFE_BAD_OPEN_FORMAT ; 86b815c7f3Sopenharmony_ci 87b815c7f3Sopenharmony_ci if (! (pmpeg->lamef = lame_init ())) 88b815c7f3Sopenharmony_ci return SFE_MALLOC_FAILED ; 89b815c7f3Sopenharmony_ci 90b815c7f3Sopenharmony_ci pmpeg->compression = -1.0 ; /* Unset */ 91b815c7f3Sopenharmony_ci 92b815c7f3Sopenharmony_ci lame_set_in_samplerate (pmpeg->lamef, psf->sf.samplerate) ; 93b815c7f3Sopenharmony_ci lame_set_num_channels (pmpeg->lamef, psf->sf.channels) ; 94b815c7f3Sopenharmony_ci if (lame_set_out_samplerate (pmpeg->lamef, psf->sf.samplerate) < 0) 95b815c7f3Sopenharmony_ci return SFE_MPEG_BAD_SAMPLERATE ; 96b815c7f3Sopenharmony_ci 97b815c7f3Sopenharmony_ci lame_set_write_id3tag_automatic (pmpeg->lamef, 0) ; 98b815c7f3Sopenharmony_ci 99b815c7f3Sopenharmony_ci if (!info_tag || psf->is_pipe) 100b815c7f3Sopenharmony_ci { /* Can't seek back, so force disable Xing/Lame/Info header. */ 101b815c7f3Sopenharmony_ci lame_set_bWriteVbrTag (pmpeg->lamef, 0) ; 102b815c7f3Sopenharmony_ci } ; 103b815c7f3Sopenharmony_ci 104b815c7f3Sopenharmony_ci if (psf->sf.channels == 2) 105b815c7f3Sopenharmony_ci { psf->write_short = mpeg_l3_encode_write_short_stereo ; 106b815c7f3Sopenharmony_ci psf->write_int = mpeg_l3_encode_write_int_stereo ; 107b815c7f3Sopenharmony_ci psf->write_float = mpeg_l3_encode_write_float_stereo ; 108b815c7f3Sopenharmony_ci psf->write_double = mpeg_l3_encode_write_double_stereo ; 109b815c7f3Sopenharmony_ci } 110b815c7f3Sopenharmony_ci else 111b815c7f3Sopenharmony_ci { psf->write_short = mpeg_l3_encode_write_short_mono ; 112b815c7f3Sopenharmony_ci psf->write_int = mpeg_l3_encode_write_int_mono ; 113b815c7f3Sopenharmony_ci psf->write_float = mpeg_l3_encode_write_float_mono ; 114b815c7f3Sopenharmony_ci psf->write_double = mpeg_l3_encode_write_double_mono ; 115b815c7f3Sopenharmony_ci } 116b815c7f3Sopenharmony_ci 117b815c7f3Sopenharmony_ci psf->sf.seekable = 0 ; 118b815c7f3Sopenharmony_ci psf->codec_close = mpeg_l3_encoder_close ; 119b815c7f3Sopenharmony_ci psf->byterate = mpeg_l3_encoder_byterate ; 120b815c7f3Sopenharmony_ci psf->datalength = 0 ; 121b815c7f3Sopenharmony_ci 122b815c7f3Sopenharmony_ci return 0 ; 123b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_init */ 124b815c7f3Sopenharmony_ci 125b815c7f3Sopenharmony_ciint 126b815c7f3Sopenharmony_cimpeg_l3_encoder_write_id3tag (SF_PRIVATE *psf) 127b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; 128b815c7f3Sopenharmony_ci unsigned char *id3v2_buffer ; 129b815c7f3Sopenharmony_ci int i, id3v2_size ; 130b815c7f3Sopenharmony_ci 131b815c7f3Sopenharmony_ci if (psf->have_written) 132b815c7f3Sopenharmony_ci return 0 ; 133b815c7f3Sopenharmony_ci 134b815c7f3Sopenharmony_ci if ((i = mpeg_l3_encoder_construct (psf))) 135b815c7f3Sopenharmony_ci return i ; 136b815c7f3Sopenharmony_ci 137b815c7f3Sopenharmony_ci if (psf_fseek (psf, 0, SEEK_SET) != 0) 138b815c7f3Sopenharmony_ci return SFE_NOT_SEEKABLE ; 139b815c7f3Sopenharmony_ci 140b815c7f3Sopenharmony_ci /* Safe to call multiple times. */ 141b815c7f3Sopenharmony_ci id3tag_init (pmpeg->lamef) ; 142b815c7f3Sopenharmony_ci 143b815c7f3Sopenharmony_ci for (i = 0 ; i < SF_MAX_STRINGS ; i++) 144b815c7f3Sopenharmony_ci { switch (psf->strings.data [i].type) 145b815c7f3Sopenharmony_ci { case SF_STR_TITLE : 146b815c7f3Sopenharmony_ci id3tag_set_title (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; 147b815c7f3Sopenharmony_ci break ; 148b815c7f3Sopenharmony_ci 149b815c7f3Sopenharmony_ci case SF_STR_ARTIST : 150b815c7f3Sopenharmony_ci id3tag_set_artist (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; 151b815c7f3Sopenharmony_ci break ; 152b815c7f3Sopenharmony_ci 153b815c7f3Sopenharmony_ci case SF_STR_ALBUM : 154b815c7f3Sopenharmony_ci id3tag_set_album (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; 155b815c7f3Sopenharmony_ci break ; 156b815c7f3Sopenharmony_ci 157b815c7f3Sopenharmony_ci case SF_STR_DATE : 158b815c7f3Sopenharmony_ci id3tag_set_year (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; 159b815c7f3Sopenharmony_ci break ; 160b815c7f3Sopenharmony_ci 161b815c7f3Sopenharmony_ci case SF_STR_COMMENT : 162b815c7f3Sopenharmony_ci id3tag_set_comment (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; 163b815c7f3Sopenharmony_ci break ; 164b815c7f3Sopenharmony_ci 165b815c7f3Sopenharmony_ci case SF_STR_GENRE : 166b815c7f3Sopenharmony_ci id3tag_set_genre (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; 167b815c7f3Sopenharmony_ci break ; 168b815c7f3Sopenharmony_ci 169b815c7f3Sopenharmony_ci case SF_STR_TRACKNUMBER : 170b815c7f3Sopenharmony_ci id3tag_set_track (pmpeg->lamef, psf->strings.storage + psf->strings.data [i].offset) ; 171b815c7f3Sopenharmony_ci break ; 172b815c7f3Sopenharmony_ci 173b815c7f3Sopenharmony_ci default: 174b815c7f3Sopenharmony_ci break ; 175b815c7f3Sopenharmony_ci } ; 176b815c7f3Sopenharmony_ci } ; 177b815c7f3Sopenharmony_ci 178b815c7f3Sopenharmony_ci /* The header in this case is the ID3v2 tag header. */ 179b815c7f3Sopenharmony_ci id3v2_size = lame_get_id3v2_tag (pmpeg->lamef, 0, 0) ; 180b815c7f3Sopenharmony_ci if (id3v2_size > 0) 181b815c7f3Sopenharmony_ci { psf_log_printf (psf, "Writing ID3v2 header.\n") ; 182b815c7f3Sopenharmony_ci if (! (id3v2_buffer = malloc (id3v2_size))) 183b815c7f3Sopenharmony_ci return SFE_MALLOC_FAILED ; 184b815c7f3Sopenharmony_ci lame_get_id3v2_tag (pmpeg->lamef, id3v2_buffer, id3v2_size) ; 185b815c7f3Sopenharmony_ci psf_fwrite (id3v2_buffer, 1, id3v2_size, psf) ; 186b815c7f3Sopenharmony_ci psf->dataoffset = id3v2_size ; 187b815c7f3Sopenharmony_ci free (id3v2_buffer) ; 188b815c7f3Sopenharmony_ci } ; 189b815c7f3Sopenharmony_ci 190b815c7f3Sopenharmony_ci return 0 ; 191b815c7f3Sopenharmony_ci} 192b815c7f3Sopenharmony_ci 193b815c7f3Sopenharmony_ciint 194b815c7f3Sopenharmony_cimpeg_l3_encoder_set_quality (SF_PRIVATE *psf, double compression) 195b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; 196b815c7f3Sopenharmony_ci int bitrate_mode ; 197b815c7f3Sopenharmony_ci int bitrate ; 198b815c7f3Sopenharmony_ci int ret ; 199b815c7f3Sopenharmony_ci 200b815c7f3Sopenharmony_ci if (compression < 0.0 || compression > 1.0) 201b815c7f3Sopenharmony_ci return SF_FALSE ; 202b815c7f3Sopenharmony_ci 203b815c7f3Sopenharmony_ci /* 204b815c7f3Sopenharmony_ci ** Save the compression setting, as we may have to re-interpret it if 205b815c7f3Sopenharmony_ci ** the bitrate mode changes. 206b815c7f3Sopenharmony_ci */ 207b815c7f3Sopenharmony_ci pmpeg->compression = compression ; 208b815c7f3Sopenharmony_ci 209b815c7f3Sopenharmony_ci bitrate_mode = mpeg_l3_encoder_get_bitrate_mode (psf) ; 210b815c7f3Sopenharmony_ci if (bitrate_mode == SF_BITRATE_MODE_VARIABLE) 211b815c7f3Sopenharmony_ci { ret = lame_set_VBR_quality (pmpeg->lamef, compression * 10.0) ; 212b815c7f3Sopenharmony_ci } 213b815c7f3Sopenharmony_ci else 214b815c7f3Sopenharmony_ci { /* Choose a bitrate. */ 215b815c7f3Sopenharmony_ci if (psf->sf.samplerate >= 32000) 216b815c7f3Sopenharmony_ci { /* MPEG-1.0, bitrates are [32,320] kbps */ 217b815c7f3Sopenharmony_ci bitrate = (320.0 - (compression * (320.0 - 32.0))) ; 218b815c7f3Sopenharmony_ci } 219b815c7f3Sopenharmony_ci else if (psf->sf.samplerate >= 16000) 220b815c7f3Sopenharmony_ci { /* MPEG-2.0, bitrates are [8,160] */ 221b815c7f3Sopenharmony_ci bitrate = (160.0 - (compression * (160.0 - 8.0))) ; 222b815c7f3Sopenharmony_ci } 223b815c7f3Sopenharmony_ci else 224b815c7f3Sopenharmony_ci { /* MPEG-2.5, bitrates are [8,64] */ 225b815c7f3Sopenharmony_ci bitrate = (64.0 - (compression * (64.0 - 8.0))) ; 226b815c7f3Sopenharmony_ci } 227b815c7f3Sopenharmony_ci 228b815c7f3Sopenharmony_ci if (bitrate_mode == SF_BITRATE_MODE_AVERAGE) 229b815c7f3Sopenharmony_ci ret = lame_set_VBR_mean_bitrate_kbps (pmpeg->lamef, bitrate) ; 230b815c7f3Sopenharmony_ci else 231b815c7f3Sopenharmony_ci ret = lame_set_brate (pmpeg->lamef, bitrate) ; 232b815c7f3Sopenharmony_ci } ; 233b815c7f3Sopenharmony_ci 234b815c7f3Sopenharmony_ci if (ret == LAME_OKAY) 235b815c7f3Sopenharmony_ci return SF_TRUE ; 236b815c7f3Sopenharmony_ci 237b815c7f3Sopenharmony_ci psf_log_printf (psf, "Failed to set lame encoder quality.\n") ; 238b815c7f3Sopenharmony_ci return SF_FALSE ; 239b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_set_quality */ 240b815c7f3Sopenharmony_ci 241b815c7f3Sopenharmony_ciint 242b815c7f3Sopenharmony_cimpeg_l3_encoder_set_bitrate_mode (SF_PRIVATE *psf, int mode) 243b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; 244b815c7f3Sopenharmony_ci enum vbr_mode_e vbr_mode ; 245b815c7f3Sopenharmony_ci 246b815c7f3Sopenharmony_ci if (pmpeg->initialized) 247b815c7f3Sopenharmony_ci { psf->error = SFE_CMD_HAS_DATA ; 248b815c7f3Sopenharmony_ci return SF_FALSE ; 249b815c7f3Sopenharmony_ci } ; 250b815c7f3Sopenharmony_ci 251b815c7f3Sopenharmony_ci switch (mode) 252b815c7f3Sopenharmony_ci { case SF_BITRATE_MODE_CONSTANT : vbr_mode = vbr_off ; break ; 253b815c7f3Sopenharmony_ci case SF_BITRATE_MODE_AVERAGE : vbr_mode = vbr_abr ; break ; 254b815c7f3Sopenharmony_ci case SF_BITRATE_MODE_VARIABLE : vbr_mode = vbr_default ; break ; 255b815c7f3Sopenharmony_ci default : 256b815c7f3Sopenharmony_ci psf->error = SFE_BAD_COMMAND_PARAM ; 257b815c7f3Sopenharmony_ci return SF_FALSE ; 258b815c7f3Sopenharmony_ci } ; 259b815c7f3Sopenharmony_ci 260b815c7f3Sopenharmony_ci if (lame_set_VBR (pmpeg->lamef, vbr_mode) == LAME_OKAY) 261b815c7f3Sopenharmony_ci { /* Re-evaluate the compression setting. */ 262b815c7f3Sopenharmony_ci return mpeg_l3_encoder_set_quality (psf, pmpeg->compression) ; 263b815c7f3Sopenharmony_ci } ; 264b815c7f3Sopenharmony_ci 265b815c7f3Sopenharmony_ci psf_log_printf (psf, "Failed to set LAME vbr mode to %d.\n", vbr_mode) ; 266b815c7f3Sopenharmony_ci return SF_FALSE ; 267b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_set_bitrate_mode */ 268b815c7f3Sopenharmony_ci 269b815c7f3Sopenharmony_ciint 270b815c7f3Sopenharmony_cimpeg_l3_encoder_get_bitrate_mode (SF_PRIVATE *psf) 271b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; 272b815c7f3Sopenharmony_ci enum vbr_mode_e vbr_mode ; 273b815c7f3Sopenharmony_ci 274b815c7f3Sopenharmony_ci vbr_mode = lame_get_VBR (pmpeg->lamef) ; 275b815c7f3Sopenharmony_ci 276b815c7f3Sopenharmony_ci if (vbr_mode == vbr_off) 277b815c7f3Sopenharmony_ci return SF_BITRATE_MODE_CONSTANT ; 278b815c7f3Sopenharmony_ci if (vbr_mode == vbr_abr) 279b815c7f3Sopenharmony_ci return SF_BITRATE_MODE_AVERAGE ; 280b815c7f3Sopenharmony_ci if (vbr_mode == vbr_default || vbr_mode < vbr_max_indicator) 281b815c7f3Sopenharmony_ci return SF_BITRATE_MODE_VARIABLE ; 282b815c7f3Sopenharmony_ci 283b815c7f3Sopenharmony_ci /* Something is wrong. */ 284b815c7f3Sopenharmony_ci psf->error = SFE_INTERNAL ; 285b815c7f3Sopenharmony_ci return -1 ; 286b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_get_bitrate_mode */ 287b815c7f3Sopenharmony_ci 288b815c7f3Sopenharmony_ci 289b815c7f3Sopenharmony_ci/*----------------------------------------------------------------------------------------------- 290b815c7f3Sopenharmony_ci** Private functions. 291b815c7f3Sopenharmony_ci*/ 292b815c7f3Sopenharmony_ci 293b815c7f3Sopenharmony_cistatic int 294b815c7f3Sopenharmony_cimpeg_l3_encoder_close (SF_PRIVATE *psf) 295b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE* pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; 296b815c7f3Sopenharmony_ci int ret, len ; 297b815c7f3Sopenharmony_ci sf_count_t pos ; 298b815c7f3Sopenharmony_ci unsigned char *buffer ; 299b815c7f3Sopenharmony_ci 300b815c7f3Sopenharmony_ci /* Magic number 7200 comes from a comment in lame.h */ 301b815c7f3Sopenharmony_ci len = 7200 ; 302b815c7f3Sopenharmony_ci if (! (buffer = malloc (len))) 303b815c7f3Sopenharmony_ci return SFE_MALLOC_FAILED ; 304b815c7f3Sopenharmony_ci ret = lame_encode_flush (pmpeg->lamef, buffer, len) ; 305b815c7f3Sopenharmony_ci if (ret > 0) 306b815c7f3Sopenharmony_ci psf_fwrite (buffer, 1, ret, psf) ; 307b815c7f3Sopenharmony_ci 308b815c7f3Sopenharmony_ci /* 309b815c7f3Sopenharmony_ci ** Write an IDv1 trailer. The whole tag structure is always 128 bytes, so is 310b815c7f3Sopenharmony_ci ** guaranteed to fit in the buffer allocated above. 311b815c7f3Sopenharmony_ci */ 312b815c7f3Sopenharmony_ci ret = lame_get_id3v1_tag (pmpeg->lamef, buffer, len) ; 313b815c7f3Sopenharmony_ci if (ret > 0) 314b815c7f3Sopenharmony_ci { psf_log_printf (psf, " Writing ID3v1 trailer.\n") ; 315b815c7f3Sopenharmony_ci psf_fwrite (buffer, 1, ret, psf) ; 316b815c7f3Sopenharmony_ci } ; 317b815c7f3Sopenharmony_ci 318b815c7f3Sopenharmony_ci /* 319b815c7f3Sopenharmony_ci ** If possible, seek back and write the LAME/XING/Info headers. This 320b815c7f3Sopenharmony_ci ** contains information about the whole file and a seek table, and can 321b815c7f3Sopenharmony_ci ** only be written after encoding. 322b815c7f3Sopenharmony_ci ** 323b815c7f3Sopenharmony_ci ** If enabled, Lame wrote an empty header at the beginning of the data 324b815c7f3Sopenharmony_ci ** that we now fill in. 325b815c7f3Sopenharmony_ci */ 326b815c7f3Sopenharmony_ci ret = lame_get_lametag_frame (pmpeg->lamef, 0, 0) ; 327b815c7f3Sopenharmony_ci if (ret > 0) 328b815c7f3Sopenharmony_ci { if (ret > len) 329b815c7f3Sopenharmony_ci { len = ret ; 330b815c7f3Sopenharmony_ci free (buffer) ; 331b815c7f3Sopenharmony_ci if (! (buffer = malloc (len))) 332b815c7f3Sopenharmony_ci return SFE_MALLOC_FAILED ; 333b815c7f3Sopenharmony_ci } ; 334b815c7f3Sopenharmony_ci psf_log_printf (psf, " Writing LAME info header at offset %d, %d bytes.\n", 335b815c7f3Sopenharmony_ci psf->dataoffset, len) ; 336b815c7f3Sopenharmony_ci lame_get_lametag_frame (pmpeg->lamef, buffer, len) ; 337b815c7f3Sopenharmony_ci pos = psf_ftell (psf) ; 338b815c7f3Sopenharmony_ci if (psf_fseek (psf, psf->dataoffset, SEEK_SET) == psf->dataoffset) 339b815c7f3Sopenharmony_ci { psf_fwrite (buffer, 1, ret, psf) ; 340b815c7f3Sopenharmony_ci psf_fseek (psf, pos, SEEK_SET) ; 341b815c7f3Sopenharmony_ci } ; 342b815c7f3Sopenharmony_ci } ; 343b815c7f3Sopenharmony_ci free (buffer) ; 344b815c7f3Sopenharmony_ci 345b815c7f3Sopenharmony_ci free (pmpeg->block) ; 346b815c7f3Sopenharmony_ci pmpeg->block = NULL ; 347b815c7f3Sopenharmony_ci 348b815c7f3Sopenharmony_ci if (pmpeg->lamef) 349b815c7f3Sopenharmony_ci { lame_close (pmpeg->lamef) ; 350b815c7f3Sopenharmony_ci pmpeg->lamef = NULL ; 351b815c7f3Sopenharmony_ci } ; 352b815c7f3Sopenharmony_ci 353b815c7f3Sopenharmony_ci return 0 ; 354b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_close */ 355b815c7f3Sopenharmony_ci 356b815c7f3Sopenharmony_cistatic void 357b815c7f3Sopenharmony_cimpeg_l3_encoder_log_config (SF_PRIVATE *psf, lame_t lamef) 358b815c7f3Sopenharmony_ci{ const char *version ; 359b815c7f3Sopenharmony_ci const char *chn_mode ; 360b815c7f3Sopenharmony_ci 361b815c7f3Sopenharmony_ci switch (lame_get_version (lamef)) 362b815c7f3Sopenharmony_ci { case 0 : version = "2" ; break ; 363b815c7f3Sopenharmony_ci case 1 : version = "1" ; break ; 364b815c7f3Sopenharmony_ci case 2 : version = "2.5" ; break ; 365b815c7f3Sopenharmony_ci default : version = "unknown!?" ; break ; 366b815c7f3Sopenharmony_ci } ; 367b815c7f3Sopenharmony_ci switch (lame_get_mode (lamef)) 368b815c7f3Sopenharmony_ci { case STEREO : chn_mode = "stereo" ; break ; 369b815c7f3Sopenharmony_ci case JOINT_STEREO : chn_mode = "joint-stereo" ; break ; 370b815c7f3Sopenharmony_ci case MONO : chn_mode = "mono" ; break ; 371b815c7f3Sopenharmony_ci default : chn_mode = "unknown!?" ; break ; 372b815c7f3Sopenharmony_ci } ; 373b815c7f3Sopenharmony_ci psf_log_printf (psf, " MPEG Version : %s\n", version) ; 374b815c7f3Sopenharmony_ci psf_log_printf (psf, " Block samples : %d\n", lame_get_framesize (lamef)) ; 375b815c7f3Sopenharmony_ci psf_log_printf (psf, " Channel mode : %s\n", chn_mode) ; 376b815c7f3Sopenharmony_ci psf_log_printf (psf, " Samplerate : %d\n", lame_get_out_samplerate (lamef)) ; 377b815c7f3Sopenharmony_ci psf_log_printf (psf, " Encoder mode : ") ; 378b815c7f3Sopenharmony_ci switch (lame_get_VBR (lamef)) 379b815c7f3Sopenharmony_ci { case vbr_off : 380b815c7f3Sopenharmony_ci psf_log_printf (psf, "CBR\n") ; 381b815c7f3Sopenharmony_ci psf_log_printf (psf, " Bitrate : %d kbps\n", lame_get_brate (lamef)) ; 382b815c7f3Sopenharmony_ci break ; 383b815c7f3Sopenharmony_ci case vbr_abr : 384b815c7f3Sopenharmony_ci psf_log_printf (psf, "ABR\n") ; 385b815c7f3Sopenharmony_ci psf_log_printf (psf, " Mean Bitrate : %d kbps\n", lame_get_VBR_mean_bitrate_kbps (lamef)) ; 386b815c7f3Sopenharmony_ci break ; 387b815c7f3Sopenharmony_ci 388b815c7f3Sopenharmony_ci case vbr_mt : 389b815c7f3Sopenharmony_ci case vbr_default : 390b815c7f3Sopenharmony_ci psf_log_printf (psf, "VBR\n") ; 391b815c7f3Sopenharmony_ci psf_log_printf (psf, " Quality : %d\n", lame_get_VBR_q (lamef)) ; 392b815c7f3Sopenharmony_ci break ; 393b815c7f3Sopenharmony_ci 394b815c7f3Sopenharmony_ci default: 395b815c7f3Sopenharmony_ci psf_log_printf (psf, "Unknown!? (%d)\n", lame_get_VBR (lamef)) ; 396b815c7f3Sopenharmony_ci break ; 397b815c7f3Sopenharmony_ci } ; 398b815c7f3Sopenharmony_ci 399b815c7f3Sopenharmony_ci psf_log_printf (psf, " Encoder delay : %d\n", lame_get_encoder_delay (lamef)) ; 400b815c7f3Sopenharmony_ci psf_log_printf (psf, " Write INFO header : %d\n", lame_get_bWriteVbrTag (lamef)) ; 401b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_log_config */ 402b815c7f3Sopenharmony_ci 403b815c7f3Sopenharmony_cistatic int 404b815c7f3Sopenharmony_cimpeg_l3_encoder_construct (SF_PRIVATE *psf) 405b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; 406b815c7f3Sopenharmony_ci int frame_samples_per_channel ; 407b815c7f3Sopenharmony_ci 408b815c7f3Sopenharmony_ci if (pmpeg->initialized == SF_FALSE) 409b815c7f3Sopenharmony_ci { if (lame_init_params (pmpeg->lamef) < 0) 410b815c7f3Sopenharmony_ci { psf_log_printf (psf, "Failed to initialize lame encoder!\n") ; 411b815c7f3Sopenharmony_ci return SFE_INTERNAL ; 412b815c7f3Sopenharmony_ci } ; 413b815c7f3Sopenharmony_ci 414b815c7f3Sopenharmony_ci psf_log_printf (psf, "Initialized LAME encoder.\n") ; 415b815c7f3Sopenharmony_ci mpeg_l3_encoder_log_config (psf, pmpeg->lamef) ; 416b815c7f3Sopenharmony_ci 417b815c7f3Sopenharmony_ci frame_samples_per_channel = lame_get_framesize (pmpeg->lamef) ; 418b815c7f3Sopenharmony_ci 419b815c7f3Sopenharmony_ci /* 420b815c7f3Sopenharmony_ci * Suggested output buffer size in bytes from lame.h comment is 421b815c7f3Sopenharmony_ci * 1.25 * samples + 7200 422b815c7f3Sopenharmony_ci */ 423b815c7f3Sopenharmony_ci pmpeg->block_len = (frame_samples_per_channel * 4) / 3 + 7200 ; 424b815c7f3Sopenharmony_ci pmpeg->frame_samples = frame_samples_per_channel * psf->sf.channels ; 425b815c7f3Sopenharmony_ci 426b815c7f3Sopenharmony_ci pmpeg->block = malloc (pmpeg->block_len) ; 427b815c7f3Sopenharmony_ci if (!pmpeg->block) 428b815c7f3Sopenharmony_ci return SFE_MALLOC_FAILED ; 429b815c7f3Sopenharmony_ci 430b815c7f3Sopenharmony_ci pmpeg->initialized = SF_TRUE ; 431b815c7f3Sopenharmony_ci } ; 432b815c7f3Sopenharmony_ci 433b815c7f3Sopenharmony_ci return 0 ; 434b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_construct */ 435b815c7f3Sopenharmony_ci 436b815c7f3Sopenharmony_cistatic int 437b815c7f3Sopenharmony_cimpeg_l3_encoder_byterate (SF_PRIVATE *psf) 438b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE *) psf->codec_data ; 439b815c7f3Sopenharmony_ci int bitrate_mode ; 440b815c7f3Sopenharmony_ci int byterate ; 441b815c7f3Sopenharmony_ci float calculated_byterate ; 442b815c7f3Sopenharmony_ci 443b815c7f3Sopenharmony_ci bitrate_mode = mpeg_l3_encoder_get_bitrate_mode (psf) ; 444b815c7f3Sopenharmony_ci byterate = (lame_get_brate (pmpeg->lamef) + 7) / 8 ; 445b815c7f3Sopenharmony_ci 446b815c7f3Sopenharmony_ci if (bitrate_mode == SF_BITRATE_MODE_VARIABLE) 447b815c7f3Sopenharmony_ci { /* 448b815c7f3Sopenharmony_ci ** For VBR, lame_get_brate returns the minimum bitrate, so calculate the 449b815c7f3Sopenharmony_ci ** average byterate so far. 450b815c7f3Sopenharmony_ci */ 451b815c7f3Sopenharmony_ci calculated_byterate = psf_ftell (psf) - psf->dataoffset ; 452b815c7f3Sopenharmony_ci calculated_byterate /= (float) psf->write_current ; 453b815c7f3Sopenharmony_ci calculated_byterate *= (float) psf->sf.samplerate ; 454b815c7f3Sopenharmony_ci 455b815c7f3Sopenharmony_ci return SF_MIN (byterate, (int) calculated_byterate) ; 456b815c7f3Sopenharmony_ci } 457b815c7f3Sopenharmony_ci 458b815c7f3Sopenharmony_ci return byterate ; 459b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_byterate */ 460b815c7f3Sopenharmony_ci 461b815c7f3Sopenharmony_cistatic sf_count_t 462b815c7f3Sopenharmony_cimpeg_l3_encode_write_short_mono (SF_PRIVATE *psf, const short *ptr, sf_count_t len) 463b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 464b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 465b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 466b815c7f3Sopenharmony_ci 467b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 468b815c7f3Sopenharmony_ci return 0 ; 469b815c7f3Sopenharmony_ci 470b815c7f3Sopenharmony_ci while (len) 471b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; 472b815c7f3Sopenharmony_ci 473b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; 474b815c7f3Sopenharmony_ci if (nbytes < 0) 475b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 476b815c7f3Sopenharmony_ci break ; 477b815c7f3Sopenharmony_ci } ; 478b815c7f3Sopenharmony_ci 479b815c7f3Sopenharmony_ci if (nbytes) 480b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 481b815c7f3Sopenharmony_ci if (writen != nbytes) 482b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 483b815c7f3Sopenharmony_ci } ; 484b815c7f3Sopenharmony_ci } ; 485b815c7f3Sopenharmony_ci 486b815c7f3Sopenharmony_ci total += writecount ; 487b815c7f3Sopenharmony_ci len -= writecount ; 488b815c7f3Sopenharmony_ci } ; 489b815c7f3Sopenharmony_ci 490b815c7f3Sopenharmony_ci return total ; 491b815c7f3Sopenharmony_ci} 492b815c7f3Sopenharmony_ci 493b815c7f3Sopenharmony_ci 494b815c7f3Sopenharmony_cistatic sf_count_t 495b815c7f3Sopenharmony_cimpeg_l3_encode_write_short_stereo (SF_PRIVATE *psf, const short *ptr, sf_count_t len) 496b815c7f3Sopenharmony_ci{ BUF_UNION ubuf ; 497b815c7f3Sopenharmony_ci MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 498b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 499b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 500b815c7f3Sopenharmony_ci 501b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 502b815c7f3Sopenharmony_ci return 0 ; 503b815c7f3Sopenharmony_ci 504b815c7f3Sopenharmony_ci const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.sbuf), pmpeg->frame_samples) ; 505b815c7f3Sopenharmony_ci while (len) 506b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, max_samples) ; 507b815c7f3Sopenharmony_ci /* 508b815c7f3Sopenharmony_ci * An oversight, but lame_encode_buffer_interleaved() lacks a const. 509b815c7f3Sopenharmony_ci * As such, need another memcpy to not cause a warning. 510b815c7f3Sopenharmony_ci */ 511b815c7f3Sopenharmony_ci memcpy (ubuf.sbuf, ptr + total, writecount) ; 512b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_interleaved (pmpeg->lamef, ubuf.sbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; 513b815c7f3Sopenharmony_ci if (nbytes < 0) 514b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 515b815c7f3Sopenharmony_ci break ; 516b815c7f3Sopenharmony_ci } ; 517b815c7f3Sopenharmony_ci 518b815c7f3Sopenharmony_ci if (nbytes) 519b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 520b815c7f3Sopenharmony_ci if (writen != nbytes) 521b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 522b815c7f3Sopenharmony_ci } ; 523b815c7f3Sopenharmony_ci } ; 524b815c7f3Sopenharmony_ci 525b815c7f3Sopenharmony_ci total += writecount ; 526b815c7f3Sopenharmony_ci len -= writecount ; 527b815c7f3Sopenharmony_ci } ; 528b815c7f3Sopenharmony_ci 529b815c7f3Sopenharmony_ci return total ; 530b815c7f3Sopenharmony_ci} 531b815c7f3Sopenharmony_ci 532b815c7f3Sopenharmony_ci 533b815c7f3Sopenharmony_cistatic sf_count_t 534b815c7f3Sopenharmony_cimpeg_l3_encode_write_int_mono (SF_PRIVATE *psf, const int *ptr, sf_count_t len) 535b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 536b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 537b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 538b815c7f3Sopenharmony_ci 539b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 540b815c7f3Sopenharmony_ci return 0 ; 541b815c7f3Sopenharmony_ci 542b815c7f3Sopenharmony_ci while (len) 543b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; 544b815c7f3Sopenharmony_ci 545b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_int (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; 546b815c7f3Sopenharmony_ci if (nbytes < 0) 547b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 548b815c7f3Sopenharmony_ci break ; 549b815c7f3Sopenharmony_ci } ; 550b815c7f3Sopenharmony_ci 551b815c7f3Sopenharmony_ci if (nbytes) 552b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 553b815c7f3Sopenharmony_ci if (writen != nbytes) 554b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 555b815c7f3Sopenharmony_ci } ; 556b815c7f3Sopenharmony_ci } ; 557b815c7f3Sopenharmony_ci 558b815c7f3Sopenharmony_ci total += writecount ; 559b815c7f3Sopenharmony_ci len -= writecount ; 560b815c7f3Sopenharmony_ci } ; 561b815c7f3Sopenharmony_ci 562b815c7f3Sopenharmony_ci return total ; 563b815c7f3Sopenharmony_ci} 564b815c7f3Sopenharmony_ci 565b815c7f3Sopenharmony_ci 566b815c7f3Sopenharmony_cistatic sf_count_t 567b815c7f3Sopenharmony_cimpeg_l3_encode_write_int_stereo (SF_PRIVATE *psf, const int *ptr, sf_count_t len) 568b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 569b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 570b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 571b815c7f3Sopenharmony_ci 572b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 573b815c7f3Sopenharmony_ci return 0 ; 574b815c7f3Sopenharmony_ci 575b815c7f3Sopenharmony_ci while (len) 576b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; 577b815c7f3Sopenharmony_ci 578b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_interleaved_int (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; 579b815c7f3Sopenharmony_ci if (nbytes < 0) 580b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 581b815c7f3Sopenharmony_ci break ; 582b815c7f3Sopenharmony_ci } ; 583b815c7f3Sopenharmony_ci 584b815c7f3Sopenharmony_ci if (nbytes) 585b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 586b815c7f3Sopenharmony_ci if (writen != nbytes) 587b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 588b815c7f3Sopenharmony_ci } ; 589b815c7f3Sopenharmony_ci } ; 590b815c7f3Sopenharmony_ci 591b815c7f3Sopenharmony_ci total += writecount ; 592b815c7f3Sopenharmony_ci len -= writecount ; 593b815c7f3Sopenharmony_ci } ; 594b815c7f3Sopenharmony_ci 595b815c7f3Sopenharmony_ci return total ; 596b815c7f3Sopenharmony_ci} 597b815c7f3Sopenharmony_ci 598b815c7f3Sopenharmony_ci 599b815c7f3Sopenharmony_cistatic sf_count_t 600b815c7f3Sopenharmony_cimpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t len) 601b815c7f3Sopenharmony_ci{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 602b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 603b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 604b815c7f3Sopenharmony_ci 605b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 606b815c7f3Sopenharmony_ci return 0 ; 607b815c7f3Sopenharmony_ci 608b815c7f3Sopenharmony_ci while (len) 609b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; 610b815c7f3Sopenharmony_ci 611b815c7f3Sopenharmony_ci if (psf->norm_float) 612b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_ieee_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; 613b815c7f3Sopenharmony_ci else 614b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; 615b815c7f3Sopenharmony_ci if (nbytes < 0) 616b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 617b815c7f3Sopenharmony_ci break ; 618b815c7f3Sopenharmony_ci } ; 619b815c7f3Sopenharmony_ci 620b815c7f3Sopenharmony_ci if (nbytes) 621b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 622b815c7f3Sopenharmony_ci if (writen != nbytes) 623b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 624b815c7f3Sopenharmony_ci } ; 625b815c7f3Sopenharmony_ci } ; 626b815c7f3Sopenharmony_ci 627b815c7f3Sopenharmony_ci total += writecount ; 628b815c7f3Sopenharmony_ci len -= writecount ; 629b815c7f3Sopenharmony_ci } ; 630b815c7f3Sopenharmony_ci 631b815c7f3Sopenharmony_ci return total ; 632b815c7f3Sopenharmony_ci} 633b815c7f3Sopenharmony_ci 634b815c7f3Sopenharmony_ci 635b815c7f3Sopenharmony_cistatic inline void 636b815c7f3Sopenharmony_cinormalize_float (float *dest, const float *src, sf_count_t count, float norm_fact) 637b815c7f3Sopenharmony_ci{ while (--count >= 0) 638b815c7f3Sopenharmony_ci { dest [count] = src [count] * norm_fact ; 639b815c7f3Sopenharmony_ci } ; 640b815c7f3Sopenharmony_ci} 641b815c7f3Sopenharmony_ci 642b815c7f3Sopenharmony_ci 643b815c7f3Sopenharmony_cistatic sf_count_t 644b815c7f3Sopenharmony_cimpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t len) 645b815c7f3Sopenharmony_ci{ BUF_UNION ubuf ; 646b815c7f3Sopenharmony_ci MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 647b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 648b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 649b815c7f3Sopenharmony_ci 650b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 651b815c7f3Sopenharmony_ci return 0 ; 652b815c7f3Sopenharmony_ci 653b815c7f3Sopenharmony_ci const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.fbuf), pmpeg->frame_samples) ; 654b815c7f3Sopenharmony_ci while (len) 655b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, max_samples) ; 656b815c7f3Sopenharmony_ci 657b815c7f3Sopenharmony_ci if (psf->norm_float) 658b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; 659b815c7f3Sopenharmony_ci else 660b815c7f3Sopenharmony_ci { /* Lame lacks a non-normalized interleaved float write. Bummer. */ 661b815c7f3Sopenharmony_ci normalize_float (ubuf.fbuf, ptr + total, writecount, 1.0 / (float) 0x8000) ; 662b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ubuf.fbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; 663b815c7f3Sopenharmony_ci } 664b815c7f3Sopenharmony_ci 665b815c7f3Sopenharmony_ci if (nbytes < 0) 666b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 667b815c7f3Sopenharmony_ci break ; 668b815c7f3Sopenharmony_ci } ; 669b815c7f3Sopenharmony_ci 670b815c7f3Sopenharmony_ci if (nbytes) 671b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 672b815c7f3Sopenharmony_ci if (writen != nbytes) 673b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 674b815c7f3Sopenharmony_ci } ; 675b815c7f3Sopenharmony_ci } ; 676b815c7f3Sopenharmony_ci 677b815c7f3Sopenharmony_ci total += writecount ; 678b815c7f3Sopenharmony_ci len -= writecount ; 679b815c7f3Sopenharmony_ci } ; 680b815c7f3Sopenharmony_ci 681b815c7f3Sopenharmony_ci return total ; 682b815c7f3Sopenharmony_ci} 683b815c7f3Sopenharmony_ci 684b815c7f3Sopenharmony_ci 685b815c7f3Sopenharmony_cistatic inline void 686b815c7f3Sopenharmony_cinormalize_double (double *dest, const double *src, sf_count_t count, double norm_fact) 687b815c7f3Sopenharmony_ci{ while (--count >= 0) 688b815c7f3Sopenharmony_ci { dest [count] = src [count] * norm_fact ; 689b815c7f3Sopenharmony_ci } ; 690b815c7f3Sopenharmony_ci} 691b815c7f3Sopenharmony_ci 692b815c7f3Sopenharmony_ci 693b815c7f3Sopenharmony_cistatic sf_count_t 694b815c7f3Sopenharmony_cimpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t len) 695b815c7f3Sopenharmony_ci{ BUF_UNION ubuf ; 696b815c7f3Sopenharmony_ci MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 697b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 698b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 699b815c7f3Sopenharmony_ci 700b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 701b815c7f3Sopenharmony_ci return 0 ; 702b815c7f3Sopenharmony_ci 703b815c7f3Sopenharmony_ci const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.dbuf), pmpeg->frame_samples) ; 704b815c7f3Sopenharmony_ci while (len) 705b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, max_samples) ; 706b815c7f3Sopenharmony_ci 707b815c7f3Sopenharmony_ci if (psf->norm_double) 708b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; 709b815c7f3Sopenharmony_ci else 710b815c7f3Sopenharmony_ci { /* Lame lacks non-normalized double writing */ 711b815c7f3Sopenharmony_ci normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; 712b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ubuf.dbuf, NULL, writecount, pmpeg->block, pmpeg->block_len) ; 713b815c7f3Sopenharmony_ci } 714b815c7f3Sopenharmony_ci 715b815c7f3Sopenharmony_ci if (nbytes < 0) 716b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 717b815c7f3Sopenharmony_ci break ; 718b815c7f3Sopenharmony_ci } ; 719b815c7f3Sopenharmony_ci 720b815c7f3Sopenharmony_ci if (nbytes) 721b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 722b815c7f3Sopenharmony_ci if (writen != nbytes) 723b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 724b815c7f3Sopenharmony_ci } ; 725b815c7f3Sopenharmony_ci } ; 726b815c7f3Sopenharmony_ci 727b815c7f3Sopenharmony_ci total += writecount ; 728b815c7f3Sopenharmony_ci len -= writecount ; 729b815c7f3Sopenharmony_ci } ; 730b815c7f3Sopenharmony_ci 731b815c7f3Sopenharmony_ci return total ; 732b815c7f3Sopenharmony_ci} 733b815c7f3Sopenharmony_ci 734b815c7f3Sopenharmony_ci 735b815c7f3Sopenharmony_cistatic sf_count_t 736b815c7f3Sopenharmony_cimpeg_l3_encode_write_double_stereo (SF_PRIVATE *psf, const double *ptr, sf_count_t len) 737b815c7f3Sopenharmony_ci{ BUF_UNION ubuf ; 738b815c7f3Sopenharmony_ci MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; 739b815c7f3Sopenharmony_ci sf_count_t total = 0 ; 740b815c7f3Sopenharmony_ci int nbytes, writecount, writen ; 741b815c7f3Sopenharmony_ci 742b815c7f3Sopenharmony_ci if ((psf->error = mpeg_l3_encoder_construct (psf))) 743b815c7f3Sopenharmony_ci return 0 ; 744b815c7f3Sopenharmony_ci 745b815c7f3Sopenharmony_ci const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.dbuf), pmpeg->frame_samples) ; 746b815c7f3Sopenharmony_ci while (len) 747b815c7f3Sopenharmony_ci { writecount = SF_MIN (len, max_samples) ; 748b815c7f3Sopenharmony_ci 749b815c7f3Sopenharmony_ci if (psf->norm_double) 750b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; 751b815c7f3Sopenharmony_ci else 752b815c7f3Sopenharmony_ci { /* Lame lacks interleaved non-normalized double writing */ 753b815c7f3Sopenharmony_ci normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; 754b815c7f3Sopenharmony_ci nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ubuf.dbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; 755b815c7f3Sopenharmony_ci } 756b815c7f3Sopenharmony_ci 757b815c7f3Sopenharmony_ci if (nbytes < 0) 758b815c7f3Sopenharmony_ci { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; 759b815c7f3Sopenharmony_ci break ; 760b815c7f3Sopenharmony_ci } ; 761b815c7f3Sopenharmony_ci 762b815c7f3Sopenharmony_ci if (nbytes) 763b815c7f3Sopenharmony_ci { writen = psf_fwrite (pmpeg->block, 1, nbytes, psf) ; 764b815c7f3Sopenharmony_ci if (writen != nbytes) 765b815c7f3Sopenharmony_ci { psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", writen, nbytes) ; 766b815c7f3Sopenharmony_ci } ; 767b815c7f3Sopenharmony_ci } ; 768b815c7f3Sopenharmony_ci 769b815c7f3Sopenharmony_ci total += writecount ; 770b815c7f3Sopenharmony_ci len -= writecount ; 771b815c7f3Sopenharmony_ci } ; 772b815c7f3Sopenharmony_ci 773b815c7f3Sopenharmony_ci return total ; 774b815c7f3Sopenharmony_ci} 775b815c7f3Sopenharmony_ci 776b815c7f3Sopenharmony_ci#else /* HAVE_MPEG */ 777b815c7f3Sopenharmony_ci 778b815c7f3Sopenharmony_ciint 779b815c7f3Sopenharmony_cimpeg_l3_encoder_init (SF_PRIVATE *psf, int UNUSED (vbr)) 780b815c7f3Sopenharmony_ci{ psf_log_printf (psf, "This version of libsndfile was compiled without MPEG Layer 3 encoding support.\n") ; 781b815c7f3Sopenharmony_ci return SFE_UNIMPLEMENTED ; 782b815c7f3Sopenharmony_ci} /* mpeg_l3_encoder_init */ 783b815c7f3Sopenharmony_ci 784b815c7f3Sopenharmony_ci#endif 785