конвертировать PCM в MP3 на лету - PullRequest
2 голосов
/ 15 апреля 2019

Я пытаюсь преобразовать PCM в MP3, используя LameHelper

LameHelper, преобразует wav-файл в mp3-файл с такой строкой: lhHandle.encode ("wav.wav", "mp3.mp3", settings);

Но я хочу сделать конвертацию на лету, без необходимости писать файл wav и читать его, чтобы конвертировать в mp3.

Я пытался изменить функции LameHelper для этого, но безуспешно

В цикле for происходит сбой меньше 3 ...

Это мой код:

#include <Windows.h>
#include "lameHelper.h"
#define HEADER_LEN 52

INT ReadMyFile(LPCWSTR lpcszFilePath, CHAR** szFinalBuffIn, DWORD* dwSize)
{
    HANDLE hndlRead;
    OVERLAPPED ol = {0};
    BOOL bRetValCheck;

    hndlRead = CreateFileW(lpcszFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hndlRead != INVALID_HANDLE_VALUE)
    {
        *dwSize = GetFileSize(hndlRead, NULL);
        *szFinalBuffIn = (CHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *dwSize);

        if (szFinalBuffIn != NULL)
        {
            bRetValCheck = ReadFile(hndlRead, *szFinalBuffIn, *dwSize, NULL, &ol);

            if (!bRetValCheck)
            {
                //  If !ReadFile The Allocated Memory For Buffer Will Be Free
                HeapFree(GetProcessHeap(), 0, szFinalBuffIn);
            }
        }
        CloseHandle(hndlRead);
    }
    return 0;
}

int encode_x(CHAR* PCM_Buff, INT nPCM_Len, CHAR** Mp3Buffer, INT nMP3_Len, settings_t settings)
{
    lame_global_flags*  gfp = NULL;
    gfp = lame_init();
    lame_set_in_samplerate(gfp, settings.in_samplerate);

    //Init the id3 tag structure
    id3tag_init(gfp);
    id3tag_v2_only(gfp);


    //Setting Channels
    switch(settings.channels)
    {
    case EC_MONO:
        lame_set_mode(gfp, MONO);
        lame_set_num_channels(gfp, 1);
        break;
    case EC_STEREO:
        lame_set_mode(gfp, JOINT_STEREO);
        lame_set_num_channels(gfp, 2);
        break;
    }

    //VbrTag
    lame_set_bWriteVbrTag(gfp, 1);  
    switch(settings.enc_mode)
    {
    case EM_ABR:
        {
            int i = settings.abr_bitrate;
            if(i >= 8000)
            {
                i = (i + 500) / 1000;
            }
            if(i > 320)
            {
                i = 320;
            }
            if(i < 8)
            {
                i = 8;
            }
            lame_set_VBR(gfp, vbr_abr);
            lame_set_VBR_mean_bitrate_kbps(gfp, i);
        }
        break;
    case EM_CBR:
        lame_set_VBR(gfp, vbr_off);
        lame_set_quality(gfp, settings.quality);
        lame_set_brate(gfp, settings.cbr_bitrate);
        break;
    case EM_VBR:
        lame_set_VBR(gfp, vbr_mtrh);
        lame_set_VBR_q(gfp, settings.quality);
        break;
    }

    lame_set_out_samplerate(gfp, settings.resample_frequency);

    lame_set_findReplayGain(gfp, 1);
    lame_set_write_id3tag_automatic(gfp, 0); //Dont write id3tag, will write it myself

    if(lame_init_params(gfp) != -1)
    {
        int write = 0;
        int m = 0;
        unsigned char* buffer = new unsigned char[LAME_MAXMP3BUFFER];
        const int PCM_SIZE = 4096;
        const int MP3_SIZE = 4096;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];

        int imp3 = lame_get_id3v2_tag(gfp, buffer, LAME_MAXMP3BUFFER);
        memset(*Mp3Buffer, NULL, nMP3_Len);
        memcpy(*Mp3Buffer + m, buffer, imp3);
        m += imp3;
        long audio_pos = imp3; //store beginning of audio data

        int nConter = nPCM_Len / PCM_SIZE;
        int nExtera = nPCM_Len % PCM_SIZE;

        for (int i = 0; i < nConter; i++)
        {
            memcpy(pcm_buffer, PCM_Buff + (i*PCM_SIZE), PCM_SIZE);
            write = lame_encode_buffer_interleaved(gfp, pcm_buffer, PCM_SIZE, mp3_buffer, MP3_SIZE);            
            memcpy(*Mp3Buffer + m, mp3_buffer, write);
            m += write;
        }
        if (nExtera)
        {
            memcpy(pcm_buffer, PCM_Buff + (nConter*PCM_SIZE), nExtera);
            write = lame_encode_buffer_interleaved(gfp, pcm_buffer, nExtera, mp3_buffer, MP3_SIZE); 
            memcpy(*Mp3Buffer + m, mp3_buffer, write);
            m += write;
        }

        imp3 = lame_get_id3v1_tag(gfp, buffer, LAME_MAXMP3BUFFER);  
        memcpy(*Mp3Buffer + m, buffer, imp3);
        m += imp3;

        imp3 = lame_get_lametag_frame(gfp, buffer, LAME_MAXMP3BUFFER);
        memcpy(*Mp3Buffer + m, buffer, imp3);
        m += imp3;

        delete [] buffer;
    }

    lame_close(gfp);
    return 0;
}

VOID ConvertToMP3(CHAR* PCM_Buff, DWORD dwSiaze)
{
    lameHelper lhHandle;
    settings_t settings;
    settings.abr_bitrate = BR_32kbps;
    settings.in_samplerate = SR_44khz;
    settings.cbr_bitrate = BR_32kbps;
    settings.channels = EC_STEREO;
    settings.enc_mode = EM_CBR;

    CHAR* Mp3Buffer = (CHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSiaze/48);
    encode_x(PCM_Buff, dwSiaze, &Mp3Buffer, dwSiaze/48, settings);  
}



int main()
{
    CHAR* szWavBuff = NULL;
    DWORD dwSiaze = 0;
    ReadMyFile(L"1.wav", &szWavBuff, &dwSiaze); 

    CHAR* PCM_Buff = (CHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSiaze-HEADER_LEN);
    memcpy(PCM_Buff, szWavBuff+HEADER_LEN, dwSiaze-HEADER_LEN);
    ConvertToMP3(PCM_Buff, dwSiaze);

    HeapFree(GetProcessHeap(), 0, szWavBuff);
    return 0;
}
...