Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > TAPI и WaveIn/WaveOut.


Автор: AndreySol 14.6.2007, 00:37
На форумах несколько раз попадалось, что люди успешно делали прослушивание линии / проигрывание в линию.
Мне необходимо сделать прослушивание линии, причем желательно с момента начала набора номера (если такое возможно).
Просветите, как такое сделать ?

Автор: Romikgy 22.6.2007, 10:42
имхо теоретически можно , но подключаемый модем паралельно к линии будет ее садить сильно , и будет слышно что тя пишут :(

Автор: AndreySol 28.6.2007, 12:05
Нет параллельное подключение не нуно, нуно через сам модем прослушивать.
В принципе я разобрался как сделать прием данных с линии используя WaveIn...-функции, однако не получается затем принятые данные синхронно скармливать WaveOut..-функциям - начинается бардак, судя по всему из-за отсутствия синхронизации приема\передачи.

Автор: black_priest 28.6.2007, 18:41
Я так понимаю ты "скармливаешь" данные WaveOut для того чтобы их услышать? И если можно в двух словах как ты данные с линии получаешь, тема заинтересовала, сам со звуком вожусь. Если есть данные, то WaveOut должна их проигрывать, есть только пара тонких моментов на которых сперва можно сподкнуться.

Автор: AndreySol 29.6.2007, 00:46
Сначала обычным способом открываю линию, получаю ID-ы для "wave/in" и "wave/out".
Затем при соединении запускаю получение данных с линии в WaveIn...-функции:
Код

static int g_WaveInSize = 0;
static char g_WaveInBuffer1[2*8000];
static char g_WaveOutBuffer1[2*8000];

// ф-ция обратного вызова для WaveIn
static void CALLBACK WaveInCallback(HWAVEIN hWaveIn, UINT wMsg, DWORD dwUser, WAVEHDR* pWaveHeader, DWORD dw2)
{
    if(wMsg == WIM_DATA)
    {
        MMRESULT Error = MMSYSERR_NOERROR;
        CMyDlg* pDlg = reinterpret_cast<CMyDlg*>(dwUser);

        // общее кол-во полученных с линии данных
        g_WaveInSize += pWaveHeader->dwBytesRecorded;

        // копируем данные в буфер WaveOut...
        memcpy(g_WaveOutBuffer1, pWaveHeader->lpData, pWaveHeader->dwBytesRecorded);

        if(pDlg -> bIsProcedingWaveOut != TRUE)
        {    // запускаем прослушивание линии (WaveOut)
            pDlg -> ProcedingWaveOut();
        }

        // пишем данные в файл
        pDlg->WriteData(pWaveHeader);

        // продолжаем получение данных с линии
        if(waveInUnprepareHeader(hWaveIn, pWaveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
        {
            if(waveInPrepareHeader(hWaveIn, pWaveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
            {
                if(waveInAddBuffer(hWaveIn, pWaveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
                {

                }
            }
        }
    }
}

BOOL CMyDlg::ProcedingWaveIn()
{
    if(bIsProcedingWaveIn == TRUE)
        return TRUE;

    // подготавливаем waveIn
    if((mmResult = waveInOpen(&hWaveIn, WaveInID, &WaveFormat, (DWORD)WaveInCallback, (DWORD)this, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
    {
        GetErrorWave(mmResult, TRUE);

        return FALSE;
    }

    pWaveInHeader1 = new WAVEHDR;
    memset(pWaveInHeader1, 0, sizeof(WAVEHDR));
    pWaveInHeader1->lpData = g_WaveInBuffer1;
    pWaveInHeader1->dwBufferLength = sizeof(g_WaveInBuffer1);
    pWaveInHeader1->dwUser = NULL;
    pWaveInHeader1->dwFlags = 0;
    pWaveInHeader1->dwLoops = 0;

    if((mmResult = waveInPrepareHeader(hWaveIn, pWaveInHeader1, sizeof(WAVEHDR))) != MMSYSERR_NOERROR)
    {
        GetErrorWave(mmResult, TRUE);

        waveInClose(hWaveIn);
        return FALSE;
    }

    if((mmResult = waveInAddBuffer(hWaveIn, pWaveInHeader1, sizeof(WAVEHDR))) != MMSYSERR_NOERROR)
    {
        GetErrorWave(mmResult, TRUE);

        waveInUnprepareHeader(hWaveIn, pWaveInHeader1, sizeof(WAVEHDR));
        waveInClose(hWaveIn);
        return FALSE;
    }

    if((mmResult = waveInStart(hWaveIn)) != MMSYSERR_NOERROR)
    {
        bIsProcedingWaveIn = FALSE;

        GetErrorWave(mmResult, TRUE);

        waveInUnprepareHeader(hWaveIn, pWaveInHeader1, sizeof(WAVEHDR));
        waveInClose(hWaveIn);
        return FALSE;
    }
    else
    {    // флаг начала записи данных с линии
        bIsProcedingWaveIn = TRUE;    
        
        // подготовливаем файл для записи в него данных
        szFileWriteName = "d:\\test.wav";

        if(fileWrite.Open(szFileWriteName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
        {
            bIsOpenFileWrite = TRUE;

        }
        else
        {
            bIsOpenFileWrite = FALSE;

            return FALSE;
        }
    }

    return TRUE;
}

затем пытаюсь полученные в WaveIn данные передать в WaveOut:
Код

// ф-ция обратного вызова для WaveOut
static void CALLBACK WaveOutCallback(HWAVEOUT hWaveOut, UINT wMsg, DWORD dwUser, WAVEHDR* pWaveHeader, DWORD dw2)
{
    if(wMsg == WOM_DONE)
    {
        // подготавливаем
        if(waveOutUnprepareHeader(hWaveOut, pWaveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
        {
            if(waveOutPrepareHeader(hWaveOut, pWaveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
            {    // воспроизводим
                if(waveOutWrite(hWaveOut, pWaveHeader, sizeof(WAVEHDR)) == MMSYSERR_NOERROR)
                {

                }
            }
        }
    }
}

BOOL CMyDlg::ProcedingWaveOut()
{
    if(bIsProcedingWaveOut == TRUE)
        return TRUE;

    // подготавливаем waveOut
    if((mmResult = waveOutOpen(&hWaveOut, WAVE_MAPPER, &WaveFormat, (DWORD)WaveOutCallback, (DWORD)this, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR )
    {
        GetErrorWave(mmResult, FALSE);

        return FALSE;
    }

    pWaveOutHeader1 = new WAVEHDR;
    memset(pWaveOutHeader1, 0, sizeof(WAVEHDR));
    pWaveOutHeader1->lpData = g_WaveOutBuffer1;
    pWaveOutHeader1->dwBufferLength = sizeof(g_WaveOutBuffer1);
    pWaveOutHeader1->dwUser = NULL;
    pWaveOutHeader1->dwFlags = 0;
    pWaveOutHeader1->dwLoops = 0;

    if((mmResult = waveOutPrepareHeader(hWaveOut, pWaveOutHeader1, sizeof(WAVEHDR))) != MMSYSERR_NOERROR )
    {
        GetErrorWave(mmResult, FALSE);

        waveOutClose(hWaveOut);
        return FALSE;
    }

    if((mmResult = waveOutWrite(hWaveOut, pWaveOutHeader1, sizeof(WAVEHDR))) != MMSYSERR_NOERROR )
    {
        GetErrorWave(mmResult, FALSE);

        waveOutUnprepareHeader(hWaveOut, pWaveOutHeader1, sizeof(WAVEHDR));
        waveOutClose(hWaveOut);
        return FALSE;
    }

    // флаг начала воспроизведения
    bIsProcedingWaveOut = TRUE;
    
    return TRUE;
}

Т.е. в общем получается, что как только получена первая порция данных, в WaveInCallback копируем эти данные в буфер для WaveOut и запускаем воспроизведение.
Результат следующий - в контрольный файл входные данные пишутся прекрасно, а на прослушивании идут накладки и пропуски звука.
Какие есть идеи как синхронизировать WaveOut относительно WaveIn ?

Автор: black_priest 29.6.2007, 14:15
Вообще, в таких случаях нужно использовать принцип двойной буферизации. Т. е. при проигрывании очередного буфера функцией waveOut, следующий буфер на проигрывание уже должен быть в очереди, тогда поток воспроизведения будет непрерывным. И с получением звука тоже нужно так поступать. Насколько я помню, если не использовать это, то в момент переключения  буферов будут раздоваться щелчки.

Автор: AndreySol 7.7.2007, 11:32
Да пробовал я эту двойную буферизацию, проблемы синхронизации WaveOut относительно WaveIn она не решает.
Может еще какие мысли ?

Автор: Romikgy 7.7.2007, 18:37
Цитата(AndreySol @  7.7.2007,  10:32 Найти цитируемый пост)
Может еще какие мысли ? 

можно попробывать в цикле , читать и писать маленькими кусочками, только обезопасится от зависаний при чтении и отсутствие данных, типа таймаутов у ком порта 

Автор: AndreySol 8.7.2007, 12:09
Примерчик бы, а то ничего дельного в голову не приходит.

Кстати, проблему вобщем-то решить можно через DirectShow - после установки Voice-модема (по крайней мере у меня) появляется два фильтра, которые могут принимать и передавать данные по нему, естественно без всяких проблем. Причем используя стандартный фильтр-расщепитель сигнала (InfTee кажись) мона сигнал подать на прослушку и на запись.

Вот только знать-бы, что такие фильтры есть обязательное дело для всех Voice-модемов ?

Автор: Romikgy 8.7.2007, 12:25
имхо 
Цитата(AndreySol @  8.7.2007,  11:09 Найти цитируемый пост)
фильтр-расщепитель

часть 
Цитата(AndreySol @  8.7.2007,  11:09 Найти цитируемый пост)
DirectShow

и применяется к модемам , у которых есть 
Цитата(AndreySol @  8.7.2007,  11:09 Найти цитируемый пост)
 Voice

режим, и этот фильтр притсуствует в системе в не зависимости есть ли в системе модем вообще
имхо

Автор: black_priest 8.7.2007, 14:24
Не знаю, у меня решает. Просто может где-то ошибаешься. Оцифровывать звук и  одновременно воспроизводить его с некоторой задержкой - вполне решаемая задача с помощью waveIn/Out функций.

Автор: AndreySol 9.7.2007, 07:04
black_priest 
Блин, дайте код - хотябы тот момент где реализована прослушка линии !
 smile 

Автор: AndreySol 14.7.2007, 09:42
black_priest
отзовитесь пожалуйста !

Автор: black_priest 6.8.2007, 08:54
Я прошу прощения за паузу, но честно говоря с кодом, который прослушивает линию не могу помочь. К сожалению, я не работал с TAPI, я работал с waveIn/Out функциями и наталкивался на проблемы синхронизации о которых ты пишешь. Не совсем понимаю, что значит
Цитата
Сначала обычным способом открываю линию, получаю ID-ы для "wave/in" и "wave/out"

или под прослушкой линии имеется ввиду что-то другое?

Автор: Ciminance 24.10.2022, 06:09
Модератор: Сообщение скрыто.

Автор: Queuego 5.11.2022, 00:31
Модератор: Сообщение скрыто.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)