Аудио манипуляции и удаление некоторой части аудио - PullRequest
2 голосов
/ 08 июня 2019

Я новичок в голосовом кодировании, теперь мне удается записывать микрофон в файлы и сохранять каждые 10 секунд в файле с функцией SaveRecordtoFile (без проблем)

Теперь я хочунапример, удалить из записанных данных 2 секунды, чтобы мои выходные данные составляли 8 секунд вместо 10, в массиве randomTime 0 - это количество секунд, которое я хочу удалить ...

В цикле for я копирую данные waveHeader->lpData в новый буфер if (randomTime[i] == '1')

10 секунд:

enter image description here

удалить данные второго числа 3 и 7 как randomTime[10] = "110111011" enter image description here

Кажется, что это истинный алгоритм и должен работать, но проблема в выходных данных, некоторые из выходных данныххороши (около 70% и более), но некоторые из них повреждены

Вывод должен быть таким:

enter image description here

нонекоторые выходы (около 30% или менее) повреждены и выглядят так:

enter image description here

Я думаю, что у меня ошибка вкод, но я отлаживаю этот код в течение нескольких дней, и я не понимаю, в чем проблема?

Это мой код:

#include <Windows.h>
#include <atlstr.h>
#pragma comment(lib,"Winmm.lib")

int SetWaveFormat(WAVEFORMATEX* wf,int wFormatTag,int nChannels,int nSamplesPerSec, int nBlockAlign, int wBitsPerSample, int cbSize)
{
    int res;
    wf->wFormatTag = wFormatTag;
    wf->nChannels = nChannels;
    wf->nSamplesPerSec = nSamplesPerSec;
    wf->nBlockAlign = nBlockAlign;
    wf->wBitsPerSample = wBitsPerSample;
    wf->cbSize = cbSize;
    wf->nAvgBytesPerSec = nChannels * nSamplesPerSec * wBitsPerSample / 8;
    return 0;
}

int OpenWaveIn(HWAVEIN* hWaveIn, WAVEFORMATEX* wf)
{
    int res;
    char lpTemp[256];

    res = waveInGetNumDevs();
    if (! res )
    {
        //_debug_print("Access WaveIn channel FAILED!",1);
        return -1;
    }
    else
    {
        //_debug_print("Access WaveIn channel SUCCEED!");
    }

    // Open wave input channel
    res = waveInOpen(hWaveIn,WAVE_MAPPER, wf, (DWORD)NULL,0L,CALLBACK_WINDOW); 
    if ( res != MMSYSERR_NOERROR )
    {
        sprintf(lpTemp, "Open wave input channel FAILED, rror_Code = 0x%x", res );
        return -1;
    }
    else
    {
        //_debug_print("Open wave input channel SUCCEED!");
    }
    return 0;
}

// Prepare Wave In Header and allocate memory
int PrepareWaveIn(HWAVEIN* hWaveIn, WAVEHDR* waveHeader, DWORD dataSize)
{
    int res;
    char lpTemp[256];

    waveHeader->dwBufferLength = dataSize;
    waveHeader->dwBytesRecorded = 0;
    waveHeader->dwUser = 0;
    waveHeader->dwFlags = 0;
    waveHeader->dwLoops = 0;
    waveHeader->lpData = (char *)GlobalLock( GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, dataSize));
    memset(waveHeader->lpData, 0, dataSize );

    // Prepare Header
    res = waveInPrepareHeader(*hWaveIn, waveHeader, sizeof(WAVEHDR) ); 
    if ( res != MMSYSERR_NOERROR)
    {
        sprintf(lpTemp, "Cannot prepare wave in header, ror_Code = 0x%03X", res );
        //_debug_print(lpTemp,1);
        return -1;
    }
    else
    {
        //_debug_print("Prepare wave in header SUCCEED!");
    }

    res = waveInAddBuffer( *hWaveIn, waveHeader, sizeof(WAVEHDR) );
    if ( res != MMSYSERR_NOERROR) 
    {
        sprintf(lpTemp, "Cannot add buffer for wave in, ror_Code = 0x%03X", res );
        //_debug_print(lpTemp,1);
        return -1;
    }
    else
    {
        //_debug_print("Add buffer for wave in SUCCEED!");
    }
    return 0;
}

// Start recording speech
int StartRecord(HWAVEIN* hWaveIn)
{
    int res;

    res = waveInStart(*hWaveIn);
    if(res != MMSYSERR_NOERROR)
    {
        //_debug_print("Start recording FAILED!",1);
        return -1;
    }
    else
    {
        //_debug_print("Start recording...",1);
    }
    return 0;
}

// Stop recording speech
int StopRecord(HWAVEIN* hWaveIn, MMTIME* mmTime)
{
    int res;

    res = waveInGetPosition(*hWaveIn, mmTime, sizeof(MMTIME));
    if(res != MMSYSERR_NOERROR)
    {
        //_debug_print("Get Position of wave in FAILED!",1);
        return -1;
    }
    else
    {
        //_debug_print("Get Position of wave in SUCCEED!");
    }

    res = waveInStop(*hWaveIn);
    if(res != MMSYSERR_NOERROR)
    {
        //_debug_print("Stop recording FAILED!",1);
        return -1;
    }
    else
    {
        //_debug_print("Stop recording SUCCEED!");
    }

    res = waveInReset(*hWaveIn);
    if(res != MMSYSERR_NOERROR)
    {
        //_debug_print("Reset wave in memory FAILED!",1);
        return -1;
    }
    else
    {
        //_debug_print("Reset wave in memory SUCCEED!");
    }

    return 0;
}

// str2num
DWORD FCC(LPSTR lpStr)
{
    DWORD Number = lpStr[0] + lpStr[1] *0x100 + lpStr[2] *0x10000 + lpStr[3] *0x1000000 ;
    return Number;
}

// Save recorded speech to file
int SaveRecordtoFile(const char* fileName, WAVEFORMATEX* wf, HWAVEIN* hWaveIn, WAVEHDR* waveHeader, MMTIME* mmTime)
{
    int res;
    DWORD NumToWrite=0;
    DWORD dwNumber = 0;
    DWORD dwSamplePerSec = 0;
    LPBYTE NewBuff;
    DWORD dwNewBuffLen = 0;

    //-----------------------------------------------------------------------------------
    // delete for example 2 seconds from the recorded data
    dwSamplePerSec = waveHeader->dwBytesRecorded / 10; // 10 Secs
    dwNewBuffLen = dwSamplePerSec * 8;
    NewBuff = (LPBYTE) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewBuffLen);
    memset(NewBuff, NULL, dwNewBuffLen);
    CHAR randomTime[10] = "110111011";
    int m = 0;
    for (int i=0; i<10; i++)
    {
        if (randomTime[i] == '1')
        {
            memcpy_s(NewBuff + (m*dwSamplePerSec), dwNewBuffLen, waveHeader->lpData + (i*dwSamplePerSec), dwSamplePerSec);
            m++;
        }
    }
    //-----------------------------------------------------------------------------------

    /*waveHeader->dwBytesRecorded = mmTime->u.cb;*/

    HANDLE FileHandle = CreateFile(CString(fileName), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    dwNumber = FCC("RIFF");
    WriteFile(FileHandle, &dwNumber, 4, &NumToWrite, NULL);

    dwNumber = /*waveHeader->dwBytesRecorded*/dwNewBuffLen + 12 + sizeof(WAVEFORMATEX) + 18 + 8;
    WriteFile(FileHandle, &dwNumber, 4, &NumToWrite, NULL);

    dwNumber = FCC("WAVE");
    WriteFile(FileHandle, &dwNumber, 4, &NumToWrite, NULL);

    dwNumber = FCC("fmt ");
    WriteFile(FileHandle, &dwNumber, 4, &NumToWrite, NULL);

    dwNumber = sizeof(WAVEFORMATEX);
    WriteFile(FileHandle, &dwNumber, 4, &NumToWrite, NULL);

    WriteFile(FileHandle, wf, sizeof(WAVEFORMATEX), &NumToWrite, NULL);

    dwNumber = FCC("data");
    WriteFile(FileHandle, &dwNumber, 4, &NumToWrite, NULL);

    dwNumber = /*waveHeader->dwBytesRecorded*/dwNewBuffLen;
    WriteFile(FileHandle, &dwNumber, 4, &NumToWrite, NULL);

    WriteFile(FileHandle, NewBuff, dwNewBuffLen, &NumToWrite, NULL);
    HeapFree(GetProcessHeap(), 0, NewBuff);
    NewBuff = NULL;
    SetEndOfFile( FileHandle );
    CloseHandle( FileHandle );
    FileHandle = INVALID_HANDLE_VALUE;

    return 0;
}

// Release wave in memory
int ReleaseWaveIn(HWAVEIN* hWaveIn, WAVEHDR* waveHeader)
{
    int res;

    res = waveInUnprepareHeader(*hWaveIn, waveHeader, sizeof(WAVEHDR));
    if ( res != MMSYSERR_NOERROR ) 
    {
        //_debug_print("UnPrepare Wave In Header FAILED!",1);
        return -1;
    }
    else
    {
        //_debug_print("UnPrepare Wave In Header SUCCEED!");
    }

    res = (int)GlobalFree(GlobalHandle( waveHeader->lpData ));
    if ( res != MMSYSERR_NOERROR )
    {
        //_debug_print("Global Free FAILED!",1);
        return -1;
    }
    else
    {
        //_debug_print("Global Free SUCCEED!");
    }

    return 0;
}

// Close Wave in channel
int CloseWaveIn(HWAVEIN* hWaveIn)
{
    int res;

    res = waveInClose(*hWaveIn);
    if(res != MMSYSERR_NOERROR)
    {
        //_debug_print("Close wave in FAILED!",1);
    }
    else
    {
        //_debug_print("Close wave in SUCCEED!");
    }
    return 0;
}

int main()
{
    int numOfFiles = 0;
    // Set wave format when sampling the audio
    WAVEFORMATEX wf;
    SetWaveFormat(&wf,1,2,48000,4,16,18);

    // Open wave input channel
    HWAVEIN hWaveIn;
    OpenWaveIn(&hWaveIn,&wf);


    while (TRUE)
    {   
        // Prepare Wave In Header and allocate memory
        WAVEHDR waveHdr;
        DWORD dataSize = 192000000;

        PrepareWaveIn(&hWaveIn, &waveHdr, dataSize);
        // Start recording
        StartRecord(&hWaveIn);

        Sleep(10000);

        // Stop recording
        MMTIME mmt;
        StopRecord(&hWaveIn, &mmt);

        CHAR FileName[MAX_PATH] = {};
        wsprintfA(FileName, "Record-%d.wav", numOfFiles);
        SaveRecordtoFile(FileName, &wf, &hWaveIn, &waveHdr, &mmt);
        numOfFiles++;
        ReleaseWaveIn(&hWaveIn, &waveHdr);
    }
    CloseWaveIn(&hWaveIn);
    return 0;
}

В некоторых местах, где я читаю, я должен копировать образцы, а не байты, но поскольку я не профессионал в этом, я не знаю, как работать с образцами, я каким-то образом изменил свой код, но результат был не очень хороший

1:

//-----------------------------------------------------------------------------------
// delete for example 2 seconds from the recorded data
dwSamplePerSec = waveHeader->dwBytesRecorded / 10; // 10 Secs
dwNewBuffLen = dwSamplePerSec * 8;
NewBuff = (LPBYTE) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewBuffLen);
memset(NewBuff, NULL, dwNewBuffLen);
CHAR randomTime[10] = "110111011";
int m = 0;

BYTE* pData = (BYTE*)(waveHeader->lpData);
for (int i=0; i<10; i++)
{
    if (randomTime[i] == '1')
    {
        for (DWORD index = 0; index < dwSamplePerSec; index++)
        {
            short left = *(short*)pData; pData+=2;
            short right = *(short*)pData; pData+=2; 
            //memcpy_s(NewBuff + (m*dwSamplePerSec), dwNewBuffLen, (SHORT *)waveHeader->lpData + (i*dwSamplePerSec), dwSamplePerSec);       
        }
        m++;
    }       
}
//-----------------------------------------------------------------------------------

2:

int x = 0;
BYTE* pData = (BYTE*)(waveHeader->lpData);  
for (int i=0; i<10; i++)
{
    if (randomTime[i] == '1')
    {
        for (DWORD index = 0; index < dwSamplePerSec; index++)
        {
            //short int* pSamples = (short int *) (pData);
            short right = *(short*)pData; //pData+=2; 
            //memcpy_s(NewBuff + (m*dwSamplePerSec), dwNewBuffLen, (SHORT *)waveHeader->lpData + (i*dwSamplePerSec), dwSamplePerSec);   
            float pDataSample = (*pData - 32768) / 32768.0f;

            if (fabs(pDataSample) > 0.25f)
                NewBuff[x] = /*pSamples;// **/ right;
                //pData++;
            else
                NewBuff[x] = *pData;

            //NewBuff[x] = pDataSample;// + right;
            x++;
            pData++;
        }
        m++;
    } 
    else
    {
        pData = pData + (/*4 * */dwSamplePerSec);
    }
}

И поскольку мои 70% или более выходов хороши, я думаю, что это не из-за байтов или выборок

1 Ответ

1 голос
/ 11 июня 2019

Ваш код может разбить семпл, после этого поток не синхронизируется, и вы слышите громкий шум.

Как это происходит? Ваш размер выборки составляет 4 байта. Таким образом, вы никогда не должны копировать ничего, не кратное 4. 10 секунд аудио займет 10x48000 × 4 = 1920000 байт. Однако Sleep(10000) всегда будет около 10 секунд, но не точно 10 секунд. Таким образом, вы можете получить 1920012 байт. Тогда вы делаете:

dwSamplePerSec = waveHeader->dwBytesRecorded / 10; // 10 Secs

, который возвращает 192001 (что не кратно 4), и пар выходит из синхронизации. Если вам повезет, вы получите 1920040 байт за 10 секунд, и это число будет кратно 4 после деления на 10, и все в порядке.

...