3 Copyright (C) 2005 and later Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
37 #include "wdlcstring.h"
38 #include "lameencdec.h"
41 #if defined(_WIN32) && !defined(_WIN64)
43 #define SUPPORT_BLADE_MODE
45 /// the blade mode is only use on 32-bit windows and is completely obsolete (libmp3lame.dll API is preferable and better)
53 /* encoding formats */
55 #define BE_CONFIG_MP3 0
56 #define BE_CONFIG_LAME 256
58 /* type definitions */
60 typedef void *HBE_STREAM
;
61 typedef HBE_STREAM
*PHBE_STREAM
;
62 typedef unsigned long BE_ERR
;
66 #define BE_ERR_SUCCESSFUL 0x00000000
67 #define BE_ERR_INVALID_FORMAT 0x00000001
68 #define BE_ERR_INVALID_FORMAT_PARAMETERS 0x00000002
69 #define BE_ERR_NO_MORE_HANDLES 0x00000003
70 #define BE_ERR_INVALID_HANDLE 0x00000004
71 #define BE_ERR_BUFFER_TOO_SMALL 0x00000005
75 #define BE_MAX_HOMEPAGE 128
77 /* format specific variables */
79 #define BE_MP3_MODE_STEREO 0
80 #define BE_MP3_MODE_JSTEREO 1
81 #define BE_MP3_MODE_DUALCHANNEL 2
82 #define BE_MP3_MODE_MONO 3
87 #define CURRENT_STRUCT_VERSION 1
88 #define CURRENT_STRUCT_SIZE sizeof(BE_CONFIG) // is currently 331 bytes
90 /* OBSOLETE, VALUES STILL WORK
97 } LAME_QUALTIY_PRESET;
104 VBR_METHOD_NONE
= -1,
105 VBR_METHOD_DEFAULT
= 0,
117 LQP_NORMAL_QUALITY
=0,
122 LQP_VERYHIGH_QUALITY
,
136 } LAME_QUALTIY_PRESET
;
141 DWORD dwConfig
; // BE_CONFIG_XXXXX
142 // Currently only BE_CONFIG_MP3 is supported
147 DWORD dwSampleRate
; // 48000, 44100 and 32000 allowed. RG note: also seems to support 16000, 22050, 24000.
148 BYTE byMode
; // BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
149 WORD wBitrate
; // 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 and 320 allowed. RG note: also seems to support 8,16,24.
155 } mp3
; // BE_CONFIG_MP3
159 // STRUCTURE INFORMATION
160 DWORD dwStructVersion
;
163 // BASIC ENCODER SETTINGS
164 DWORD dwSampleRate
; // SAMPLERATE OF INPUT FILE
165 DWORD dwReSampleRate
; // DOWNSAMPLERATE, 0=ENCODER DECIDES
166 LONG nMode
; // BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
167 DWORD dwBitrate
; // CBR bitrate, VBR min bitrate
168 DWORD dwMaxBitrate
; // CBR ignored, VBR Max bitrate
169 LONG nPreset
; // Quality preset, use one of the settings of the LAME_QUALITY_PRESET enum
170 DWORD dwMpegVersion
; // FUTURE USE, MPEG-1 OR MPEG-2
171 DWORD dwPsyModel
; // FUTURE USE, SET TO 0
172 DWORD dwEmphasis
; // FUTURE USE, SET TO 0
174 // BIT STREAM SETTINGS
175 BOOL bPrivate
; // Set Private Bit (TRUE/FALSE)
176 BOOL bCRC
; // Insert CRC (TRUE/FALSE)
177 BOOL bCopyright
; // Set Copyright Bit (TRUE/FALSE)
178 BOOL bOriginal
; // Set Original Bit (TRUE/FALSE)
181 BOOL bWriteVBRHeader
; // WRITE XING VBR HEADER (TRUE/FALSE)
182 BOOL bEnableVBR
; // USE VBR ENCODING (TRUE/FALSE)
183 INT nVBRQuality
; // VBR QUALITY 0..9
184 DWORD dwVbrAbr_bps
; // Use ABR in stead of nVBRQuality
185 VBRMETHOD nVbrMethod
;
186 BOOL bNoRes
; // Disable Bit resorvoir
188 BYTE btReserved
[255-3*sizeof(DWORD
)]; // FUTURE USE, SET TO 0
190 } LHV1
; // LAME header version 1
197 BYTE byEncodingMethod
;
203 } BE_CONFIG
, *PBE_CONFIG
;
208 // BladeEnc DLL Version number
210 BYTE byDLLMajorVersion
;
211 BYTE byDLLMinorVersion
;
213 // BladeEnc Engine Version Number
224 // BladeEnc Homepage URL
226 CHAR zHomepage
[BE_MAX_HOMEPAGE
+ 1];
232 BYTE btReserved
[125];
235 } BE_VERSION
, *PBE_VERSION
;
246 BE_ERR (*beInitStream
)(PBE_CONFIG
, PDWORD
, PDWORD
, void **str
);
247 BE_ERR (*beCloseStream
)(void *str
);
248 BE_ERR (*beEncodeChunkFloatS16NI
)(void *str
, DWORD
, PFLOAT
, PFLOAT
, PBYTE
, PDWORD
);
249 BE_ERR (*beDeinitStream
)(void *str
, PBYTE
, PDWORD
);
250 BE_ERR (*beWriteInfoTag
)(HBE_STREAM
, const char *);
251 VOID (*beVersion
)(PBE_VERSION
);
254 #endif // SUPPORT_BLADE_MODE
259 #include <Carbon/Carbon.h>
265 typedef enum MPEG_mode_e
{
268 DUAL_CHANNEL
, /* LAME doesn't supports this! */
271 MAX_INDICATOR
/* Don't use this! It's used for sanity checks. */
274 typedef void *lame_t
;
277 int (*close
)(lame_t
);
279 int (*set_in_samplerate
)(lame_t
, int);
280 int (*set_num_channels
)(lame_t
,int);
281 int (*set_out_samplerate
)(lame_t
,int);
282 int (*set_quality
)(lame_t
,int);
283 int (*set_mode
)(lame_t
,MPEG_mode
);
284 int (*set_brate
)(lame_t
, int);
285 int (*init_params
)(lame_t
);
286 int (*get_framesize
)(lame_t
);
288 int (*encode_buffer_float
)(lame_t
,
289 const float buffer_l
[], /* PCM data for left channel */
290 const float buffer_r
[], /* PCM data for right channel */
291 const int nsamples
, /* number of samples per channel */
292 unsigned char* mp3buf
, /* pointer to encoded MP3 stream */
293 const int mp3buf_size
);
294 int (*encode_flush
)(lame_t
,unsigned char* mp3buf
, int size
);
296 // these are optional
297 int (*set_VBR
)(lame_t
, int);
298 int (*set_VBR_q
)(lame_t
, int);
299 int (*set_VBR_mean_bitrate_kbps
)(lame_t
, int);
300 int (*set_VBR_min_bitrate_kbps
)(lame_t
, int);
301 int (*set_VBR_max_bitrate_kbps
)(lame_t
, int);
302 size_t (*get_lametag_frame
)(lame_t
, unsigned char *, size_t);
303 const char *(*get_lame_version
)();
307 #define LAME_DEBUG_LOADING(x)
309 #define LAME_DEBUG_LOADING(x) OutputDebugString(x)
312 static char s_last_dll_file
[128];
314 static bool tryLoadDLL2(const char *name
)
317 HINSTANCE dll
= LoadLibrary(name
);
319 void *dll
=dlopen(name
,RTLD_NOW
|RTLD_LOCAL
);
322 if (!dll
) return false;
324 LAME_DEBUG_LOADING("trying to load");
325 LAME_DEBUG_LOADING(name
);
328 #define GETITEM(x) if (NULL == (*(void **)&lame.x = GetProcAddress((HINSTANCE)dll,"lame_" #x))) errcnt++;
329 #define GETITEM_NP(x) if (NULL == (*(void **)&lame.x = GetProcAddress((HINSTANCE)dll, #x))) errcnt++;
331 #define GETITEM(x) if (NULL == (*(void **)&lame.x = dlsym(dll,"lame_" #x))) errcnt++;
332 #define GETITEM_NP(x) if (NULL == (*(void **)&lame.x = dlsym(dll,#x))) errcnt++;
336 GETITEM(set_in_samplerate
)
337 GETITEM(set_num_channels
)
338 GETITEM(set_out_samplerate
)
343 GETITEM(get_framesize
)
344 GETITEM(encode_buffer_float
)
345 GETITEM(encode_flush
)
347 int errcnt2
= errcnt
;
350 GETITEM(set_VBR_mean_bitrate_kbps
)
351 GETITEM(set_VBR_min_bitrate_kbps
)
352 GETITEM(set_VBR_max_bitrate_kbps
)
353 GETITEM(get_lametag_frame
)
354 GETITEM_NP(get_lame_version
)
359 memset(&lame
, 0, sizeof(lame
));
361 LAME_DEBUG_LOADING("trying blade mode");
363 #ifdef SUPPORT_BLADE_MODE
364 // try getting blade API
365 *((void**)&bladeAPI
.beInitStream
) = (void *) GetProcAddress(dll
, "beInitStream");
366 *((void**)&bladeAPI
.beCloseStream
) = (void *) GetProcAddress(dll
, "beCloseStream");
367 *((void**)&bladeAPI
.beEncodeChunkFloatS16NI
) = (void *) GetProcAddress(dll
, "beEncodeChunkFloatS16NI");
368 *((void**)&bladeAPI
.beDeinitStream
) = (void *) GetProcAddress(dll
, "beDeinitStream");
369 *((void**)&bladeAPI
.beVersion
) = (void *) GetProcAddress(dll
, "beVersion");
370 *((void**)&bladeAPI
.beWriteInfoTag
) = (void*) GetProcAddress(dll
, "beWriteInfoTag");
373 if (bladeAPI
.beInitStream
&&
374 bladeAPI
.beCloseStream
&&
375 bladeAPI
.beEncodeChunkFloatS16NI
&&
376 bladeAPI
.beDeinitStream
&&
379 LAME_DEBUG_LOADING("got blade mode");
384 memset(&bladeAPI
, 0, sizeof(bladeAPI
));
398 LAME_DEBUG_LOADING("loaded normal mode");
400 lstrcpyn_safe(s_last_dll_file
, name
, sizeof(s_last_dll_file
));
402 // if (!strstr(name,"\\"))
403 GetModuleFileName(dll
,s_last_dll_file
, (DWORD
)sizeof(s_last_dll_file
));
405 // if (!strstr(name,"/"))
408 dladdr((void*)lame
.init
,&inf
);
410 lstrcpyn_safe(s_last_dll_file
,inf
.dli_fname
,sizeof(s_last_dll_file
));
419 static bool tryLoadDLL(const char *extrapath
, const char *dllname
)
425 lstrcpyn_safe(me
,extrapath
,sizeof(me
)-64);
426 lstrcatn(me
,"\\",sizeof(me
));
427 lstrcatn(me
,dllname
,sizeof(me
));
428 if (tryLoadDLL2(me
)) return true;
431 GetModuleFileName(NULL
,me
,sizeof(me
)-64);
435 while(p
>=me
&& *p
!='\\') p
--;
439 if (tryLoadDLL2(me
) || tryLoadDLL2(dllname
)) return true;
443 #elif defined(__APPLE__)
444 static bool tryLoadDLL(const char *extrapath
)
450 lstrcpyn_safe(me
,extrapath
,sizeof(me
)-64);
451 lstrcatn(me
,"/libmp3lame.dylib",sizeof(me
));
452 if (tryLoadDLL2(me
)) return true;
455 if (tryLoadDLL2("/Library/Application Support/libmp3lame.dylib") ||
456 tryLoadDLL2("/usr/local/lib/libmp3lame.dylib") ||
457 tryLoadDLL2("/usr/lib/libmp3lame.dylib") ||
458 tryLoadDLL2("libmp3lame.dylib")) return true;
461 CFBundleRef bund
=CFBundleGetMainBundle();
464 CFURLRef url
=CFBundleCopyBundleURL(bund
);
468 if (CFURLGetFileSystemRepresentation(url
,true,(UInt8
*)buf
,sizeof(buf
)-128))
472 while (p
>=buf
&& *p
!= '/') p
--;
475 strcat(buf
,"/Contents/Plugins/libmp3lame.dylib");
476 ok
= tryLoadDLL2(buf
);
480 strcpy(p
,"/libmp3lame.dylib");
481 ok
= tryLoadDLL2(buf
);
485 strcpy(p
,"/Plugins/libmp3lame.dylib");
486 ok
= tryLoadDLL2(buf
);
495 #else // generic posix
496 static bool tryLoadDLL(const char *extrapath
)
501 lstrcpyn_safe(me
,extrapath
,sizeof(me
)-64);
502 lstrcatn(me
,"/libmp3lame.so",sizeof(me
));
503 if (tryLoadDLL2(me
)) return true;
505 if (tryLoadDLL2("/usr/local/lib/libmp3lame.so")||
506 tryLoadDLL2("/usr/lib/libmp3lame.so")||
507 tryLoadDLL2("libmp3lame.so")||
508 tryLoadDLL2("/usr/local/lib/libmp3lame.so.0")||
509 tryLoadDLL2("/usr/lib/libmp3lame.so.0")||
510 tryLoadDLL2("libmp3lame.so.0")) return true;
513 sprintf(tmp
,"/proc/%d/exe",getpid());
516 if (readlink(tmp
,buf
,sizeof(buf
)-128)>0 && buf
[0])
520 while (p
>buf
&& *p
!= '/') p
--;
523 strcpy(p
,"/Plugins/libmp3lame.so");
524 if (tryLoadDLL2(buf
)) return true;
526 strcpy(p
,"/libmp3lame.so");
527 if (tryLoadDLL2(buf
)) return true;
535 void LameEncoder::InitDLL(const char *extrapath
, bool forceRetry
)
541 else if (a
> 30) return; // give up
547 if (tryLoadDLL(extrapath
, "libmp3lame64.dll")||
548 tryLoadDLL(extrapath
, "libmp3lame.dll")||
549 tryLoadDLL(extrapath
, "lame_enc64.dll")||
550 tryLoadDLL(extrapath
, "lame_enc.dll")) a
= -1;
552 if (tryLoadDLL(extrapath
, "libmp3lame.dll") ||
553 tryLoadDLL(extrapath
, "lame_enc.dll")) a
= -1;
556 if (tryLoadDLL(extrapath
)) a
=-1;
560 const char *LameEncoder::GetLibName() { return s_last_dll_file
; }
562 const char *LameEncoder::GetInfo()
564 static char buf
[128];
565 int ver
= CheckDLL();
566 if (!ver
) return NULL
;
567 #ifdef SUPPORT_BLADE_MODE
571 if (bladeAPI
.beVersion
) bladeAPI
.beVersion(&ver
);
572 snprintf(buf
, sizeof(buf
), "LAME/BladeAPI %d.%d", ver
.byMajorVersion
, ver
.byMinorVersion
);
576 const char *p
= lame
.get_lame_version
? lame
.get_lame_version() : NULL
;
579 snprintf(buf
, sizeof(buf
), "LAME %s", p
);
585 int LameEncoder::CheckDLL() // returns 1 for lame API, 2 for Blade, 0 for none
590 !lame
.set_in_samplerate
||
591 !lame
.set_num_channels
||
592 !lame
.set_out_samplerate
||
597 !lame
.get_framesize
||
598 !lame
.encode_buffer_float
||
601 #ifdef SUPPORT_BLADE_MODE
602 if (bladeAPI
.beInitStream
&&
603 bladeAPI
.beCloseStream
&&
604 bladeAPI
.beEncodeChunkFloatS16NI
&&
605 bladeAPI
.beDeinitStream
&&
606 bladeAPI
.beVersion
) return 2;
615 LameEncoder::LameEncoder(int srate
, int nch
, int bitrate
, int stereomode
, int quality
, int vbrmethod
, int vbrquality
, int vbrmax
, int abr
)
618 m_encmode
= CheckDLL();
628 m_encoder_nch
= stereomode
== 3 ? 1 : m_nch
;
630 #ifdef SUPPORT_BLADE_MODE
634 memset(&beConfig
,0,sizeof(beConfig
));
635 beConfig
.dwConfig
= BE_CONFIG_LAME
;
637 beConfig
.format
.LHV1
.dwStructVersion
= 1;
638 beConfig
.format
.LHV1
.dwStructSize
= sizeof(beConfig
);
639 beConfig
.format
.LHV1
.dwSampleRate
= srate
;
640 if (m_encoder_nch
== 1) beConfig
.format
.LHV1
.nMode
= BE_MP3_MODE_MONO
;
641 else beConfig
.format
.LHV1
.nMode
= stereomode
; //bitrate >= 192 ? BE_MP3_MODE_STEREO : BE_MP3_MODE_JSTEREO;
643 beConfig
.format
.LHV1
.dwBitrate
=bitrate
;
644 beConfig
.format
.LHV1
.dwMaxBitrate
=(vbrmethod
!=-1?vbrmax
:bitrate
);
645 beConfig
.format
.LHV1
.dwReSampleRate
= srate
;
647 // if mpeg 1, and bitrate is less than 32kbps per channel, switch to mpeg 2
648 if (beConfig
.format
.LHV1
.dwReSampleRate
>= 32000 && beConfig
.format
.LHV1
.dwMaxBitrate
/m_encoder_nch
<= 32)
650 beConfig
.format
.LHV1
.dwReSampleRate
/=2;
652 beConfig
.format
.LHV1
.dwMpegVersion
= (beConfig
.format
.LHV1
.dwReSampleRate
< 32000 ? MPEG2
: MPEG1
);
654 beConfig
.format
.LHV1
.nPreset
=quality
;
656 beConfig
.format
.LHV1
.bNoRes
= 0;//1;
658 beConfig
.format
.LHV1
.bWriteVBRHeader
= 1;
659 beConfig
.format
.LHV1
.bEnableVBR
= vbrmethod
!=-1;
660 beConfig
.format
.LHV1
.nVBRQuality
= vbrquality
;
661 beConfig
.format
.LHV1
.dwVbrAbr_bps
= (vbrmethod
!=-1?1000*abr
:0);
662 beConfig
.format
.LHV1
.nVbrMethod
=(VBRMETHOD
)vbrmethod
;
665 /* LAME sets unwise bit if:
666 if (gfp->short_blocks == short_block_forced || gfp->short_blocks == short_block_dispensed || ((gfp->lowpassfreq == -1) && (gfp->highpassfreq == -1)) || // "-k"
667 (gfp->scale_left < gfp->scale_right) ||
668 (gfp->scale_left > gfp->scale_right) ||
669 (gfp->disable_reservoir && gfp->brate < 320) ||
670 gfp->noATH || gfp->ATHonly || (nAthType == 0) || gfp->in_samplerate <= 32000)
673 int out_size_bytes
=0;
675 if (bladeAPI
.beInitStream(&beConfig
, (DWORD
*)&in_size_samples
, (DWORD
*)&out_size_bytes
, (PHBE_STREAM
) &m_lamestate
) != BE_ERR_SUCCESSFUL
)
680 if (out_size_bytes
< 4096) out_size_bytes
= 4096;
681 in_size_samples
/=m_encoder_nch
;
682 outtmp
.Resize(out_size_bytes
);
687 m_lamestate
=lame
.init();
694 lame
.set_in_samplerate(m_lamestate
, srate
);
695 lame
.set_num_channels(m_lamestate
,m_encoder_nch
);
698 int maxbr
= (vbrmethod
!= -1 ? vbrmax
: bitrate
);
699 if (outrate
>=32000 && maxbr
<= 32*m_encoder_nch
) outrate
/=2;
701 lame
.set_out_samplerate(m_lamestate
,outrate
);
702 lame
.set_quality(m_lamestate
,(quality
>9 ||quality
<0) ? 0 : quality
);
703 lame
.set_mode(m_lamestate
,(MPEG_mode
) (m_encoder_nch
==1?3 :stereomode
));
704 lame
.set_brate(m_lamestate
,bitrate
);
706 //int vbrmethod (-1 no vbr), int vbrquality (nVBRQuality), int vbrmax, int abr
707 if (vbrmethod
!= -1 && lame
.set_VBR
)
710 if (vbrmethod
== 4) vm
= 3; //ABR
711 lame
.set_VBR(m_lamestate
,vm
);
713 if (lame
.set_VBR_q
) lame
.set_VBR_q(m_lamestate
,vbrquality
);
715 if (vbrmethod
== 4&&lame
.set_VBR_mean_bitrate_kbps
)
717 lame
.set_VBR_mean_bitrate_kbps(m_lamestate
,abr
);
719 if (lame
.set_VBR_max_bitrate_kbps
)
721 lame
.set_VBR_max_bitrate_kbps(m_lamestate
,vbrmax
);
723 if (lame
.set_VBR_min_bitrate_kbps
)
725 lame
.set_VBR_min_bitrate_kbps(m_lamestate
,bitrate
);
728 lame
.init_params(m_lamestate
);
729 in_size_samples
=lame
.get_framesize(m_lamestate
);
731 outtmp
.Resize(65536);
734 void LameEncoder::Encode(float *in
, int in_spls
, int spacing
)
736 if (errorstat
) return;
740 if (m_nch
> 1 && m_encoder_nch
==1)
746 for (x
= 0; x
< in_spls
; x
++)
748 float f
=in
[pos
]+in
[pos
+1];
750 spltmp
[0].Add(&f
,sizeof(float));
754 else if (m_encoder_nch
> 1) // deinterleave
759 for (x
= 0; x
< in_spls
; x
++)
763 spltmp
[0].Add(&f
,sizeof(float));
767 spltmp
[1].Add(&f
,sizeof(float));
776 for (x
= 0; x
< in_spls
; x
++)
780 spltmp
[0].Add(&f
,sizeof(float));
788 int a
= spltmp
[0].Available()/sizeof(float);
789 if (a
>= in_size_samples
) a
= in_size_samples
;
790 else if (a
<1 || in_spls
>0) break; // not enough samples available, and not flushing
793 #ifdef SUPPORT_BLADE_MODE
797 if (bladeAPI
.beEncodeChunkFloatS16NI(m_lamestate
, a
, (float*)spltmp
[0].Get(), (float*)spltmp
[m_encoder_nch
> 1].Get(),
798 (unsigned char*)outtmp
.Get(), &outa
) != BE_ERR_SUCCESSFUL
)
808 dwo
=lame
.encode_buffer_float(m_lamestate
,(float *)spltmp
[0].Get(),(float*)spltmp
[m_encoder_nch
>1].Get(), a
,(unsigned char *)outtmp
.Get(),outtmp
.GetSize());
810 outqueue
.Add(outtmp
.Get(),dwo
);
811 spltmp
[0].Advance(a
*sizeof(float));
812 if (m_encoder_nch
> 1) spltmp
[1].Advance(a
*sizeof(float));
817 #ifdef SUPPORT_BLADE_MODE
821 if (bladeAPI
.beDeinitStream(m_lamestate
, (unsigned char *)outtmp
.Get(), &dwo
) == BE_ERR_SUCCESSFUL
&& dwo
>0)
822 outqueue
.Add(outtmp
.Get(),dwo
);
827 int a
=lame
.encode_flush(m_lamestate
,(unsigned char *)outtmp
.Get(),outtmp
.GetSize());
828 if (a
>0) outqueue
.Add(outtmp
.Get(),a
);
841 static BOOL
HasUTF8(const char *_str
)
843 const unsigned char *str
= (const unsigned char *)_str
;
844 if (!str
) return FALSE
;
847 unsigned char c
= *str
;
848 if (c
>= 0xC2) // discard overlongs
850 if (c
<= 0xDF && str
[1] >=0x80 && str
[1] <= 0xBF) return TRUE
;
851 else if (c
<= 0xEF && str
[1] >=0x80 && str
[1] <= 0xBF && str
[2] >=0x80 && str
[2] <= 0xBF) return TRUE
;
852 else if (c
<= 0xF4 && str
[1] >=0x80 && str
[1] <= 0xBF && str
[2] >=0x80 && str
[2] <= 0xBF) return TRUE
;
860 LameEncoder::~LameEncoder()
862 #ifdef SUPPORT_BLADE_MODE
863 if (m_encmode
==2 && m_lamestate
)
865 if (m_vbrfile
.Get()[0] && bladeAPI
.beWriteInfoTag
)
867 // support UTF-8 filenames
868 if (HasUTF8(m_vbrfile
.Get()) && GetVersion()<0x80000000)
871 if (MultiByteToWideChar(CP_UTF8
,MB_ERR_INVALID_CHARS
,m_vbrfile
.Get(),-1,wf
,2048))
873 FILE *fp
= _wfopen(wf
,L
"r+b");
876 char tmpspace
[1024],tmpfn
[2048];
877 GetTempPath(sizeof(tmpspace
),tmpspace
);
878 GetTempFileName(tmpspace
,"lameenc",0,tmpfn
);
879 FILE *tmpfp
= fopen(tmpfn
,"wb");
882 fseek(fp
,0,SEEK_SET
);
886 int a
=fread(tmpspace
,1,sizeof(tmpspace
),fp
);
888 fwrite(tmpspace
,1,a
,tmpfp
);
893 bladeAPI
.beWriteInfoTag(m_lamestate
,tmpfn
);
896 tmpfp
= fopen(tmpfn
,"r+b");
899 fseek(tmpfp
,0,SEEK_SET
);
900 fseek(fp
,0,SEEK_SET
);
905 int a
= fread(tmpspace
,1,sizeof(tmpspace
),tmpfp
);
907 fwrite(tmpspace
,1,a
,fp
);
922 if (m_lamestate
) bladeAPI
.beWriteInfoTag(m_lamestate
,m_vbrfile
.Get());
924 else bladeAPI
.beCloseStream(m_lamestate
);
932 if (m_vbrfile
.Get()[0] && lame
.get_lametag_frame
)
934 unsigned char buf
[16384];
935 size_t a
=lame
.get_lametag_frame(m_lamestate
,buf
,sizeof(buf
));
936 if (a
>0 && a
<=sizeof(buf
))
940 if (HasUTF8(m_vbrfile
.Get()) && GetVersion()<0x80000000)
943 if (MultiByteToWideChar(CP_UTF8
,MB_ERR_INVALID_CHARS
,m_vbrfile
.Get(),-1,wf
,2048))
945 fp
= _wfopen(wf
,L
"r+b");
949 if (!fp
) fp
= fopen(m_vbrfile
.Get(),"r+b");
952 fseek(fp
,0,SEEK_SET
);
958 lame
.close(m_lamestate
);