音频处理和删除音频的某些部分

时间:2019-06-08 05:06:57

标签: c++ c voice voice-recording winmm

我是语音编码的新手,现在我成功地在文件中录制了麦克风,并使用SaveRecordtoFile功能将每10秒保存在一个文件中(这样做毫无问题)

现在,我想从记录的数据中删除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 个答案:

答案 0 :(得分:1)

您的代码可能会分解一个样本,之后流不同步,您会听到很大的声音。

如何发生?您的样本大小为4个字节。因此,切勿复制任何不是4的倍数的内容。10秒的音频将占用10x48000×4 = 1920000字节。但是Sleep(10000)将始终接近10秒,但不完全是10秒。这样就可以得到1920012字节。然后,您可以这样做:

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

返回192001(不是4的倍数),并且蒸汽不​​同步。如果幸运的话,您会在10秒内收到1920040字节,并且在除以10后仍然是4的倍数,就可以了。