蒙古论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 817|回复: 6

求助:工作需要,憋了好几天了,写不出来……

[复制链接]
发表于 2007-4-21 11:17:19 | 显示全部楼层 |阅读模式
需要一段用微机生成任意函数波形,并从声卡输出的VB代码,自己想了好几天了,“搏死”天天催,很烦!哪位大侠帮帮忙。

     要不又得加班了……
发表于 2007-4-21 11:38:42 | 显示全部楼层
看着像听天书
发表于 2007-4-23 11:21:45 | 显示全部楼层
原帖由 博英纳言 于 2007-4-21 11:17 发表
需要一段用微机生成任意函数波形,并从声卡输出的VB代码,自己想了好几天了,“搏死”天天催,很烦!哪位大侠帮帮忙。

     要不又得加班了……


这个用 vc做不太难,用vb做比较难了。
生成波形的函数,估计要用到你们自己的算法,这里就没有什么说的了。
你可以定义 byte 数组,存储你生成的波形。(其实就是幅值),byte的是256级采样的。
或者是正负127级才行。
如果你的函数采样幅度要求高就用integer或long数组来存储波形。

声卡输出呢,你需要定义好声音格式,比如采样频率采样幅度,要跟你函数生成的一致才行。
我这里有vc的例子,你可以参考做法,修改成vb的。
主要就是 waveOutOpen   wave打头的api的用法。
发表于 2007-4-23 11:25:36 | 显示全部楼层
头文件
// VocPlay.h: interface for the CVocPlay class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_VOCPLAY_H__2B681B64_C240_4632_A7DA_16D0E56E89A5__INCLUDED_)
#define AFX_VOCPLAY_H__2B681B64_C240_4632_A7DA_16D0E56E89A5__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma comment( lib, "Winmm.lib" )

#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>

//#define PCM_SAMPLERTE 8000

#define VOC_NET_FORMAT_MP3 1001

class CVocPlay : public CObject  
{////多路语音叠加播放
public:
        CVocPlay(int iID);
        virtual ~CVocPlay();

public:
        BOOL Start();
        BOOL End();
        BOOL PutNetVoc( WAVEHDR * pWave, int iID );////save to ptrlist, play voc

protected:
        int  m_iSenderID;        ////区分不同节点的数据
        BYTE * m_pMp3WaveBuff;
        CPtrList m_listRecvVoc;
        WAVEFORMATEX m_wfx;
        CCriticalSection m_csRecvVocList;        ////语音列表的多线程控制

        BOOL m_bPlayVoc;////将收到的语音数据是否送放音设备。每一路单独控制。
        BOOL        m_bHaveVoc;////1 语音数据放完,回调函数中不能自动播放语音。需要外部送语音

        BOOL  PlayDeviceOpen();
        void  PlayDeviceClose();

        static int m_iClassRef;
        static HWAVEOUT m_hWavePlay;                //放音设备句柄,一直是打开的。
        static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);

        BOOL GetNetVoc( WAVEHDR * &pWave );////取网络收到的数据
        BOOL WriteBuff2Device(WAVEHDR *pWave);
        void CleanVocBuff();////when stop play, call this to clean voc buffer

};

#endif // !defined(AFX_VOCPLAY_H__2B681B64_C240_4632_A7DA_16D0E56E89A5__INCLUDED_)

源文件
// VocPlay.cpp: implementation of the CVocPlay class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "voip.h"
#include "VocPlay.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
HWAVEOUT CVocPlay::m_hWavePlay = NULL;
int CVocPlay::m_iClassRef = 0;

CVocPlay::CVocPlay(int iID)
{
        m_iSenderID = iID;
        m_wfx.wFormatTag = WAVE_FORMAT_PCM;     // simple,  uncompressed format
        m_wfx.nChannels = 1;                    //  1 = mono,  2 = stereo
        m_wfx.nSamplesPerSec = PCM_SAMPLERTE;      
        m_wfx.nAvgBytesPerSec = PCM_SAMPLERTE * 2;      //  =  nSamplesPerSec * n.Channels * wBitsPerSample/8
        m_wfx.nBlockAlign = 1;                  //  =  n.Channels * wBitsPerSample/8
        m_wfx.wBitsPerSample = 16;               //  16 for high quality,  8 for telephone-grade
        m_wfx.cbSize = 0;   

        m_bHaveVoc = FALSE;
        m_pMp3WaveBuff = new BYTE[PCM_SAMPLERTE * 4];
        PlayDeviceOpen();
}

CVocPlay::~CVocPlay()
{
        delete [] m_pMp3WaveBuff;
        PlayDeviceClose();
}

BOOL CVocPlay::Start()
{
        m_bPlayVoc = TRUE;
        return TRUE;
}

BOOL CVocPlay::End()
{
        m_bPlayVoc = FALSE;
        PlayDeviceClose();
        return TRUE;
}

////save to ptrlist, play voc
BOOL CVocPlay:: PutNetVoc( WAVEHDR * pWave, int iID )
{
        WAVEHDR * pWavePlay;
        if( iID != m_iSenderID ) return FALSE;

        CSingleLock sl(&m_csRecvVocList);
        sl.Lock();
        m_listRecvVoc.AddTail( pWave );
        sl.Unlock();

        if( !m_bHaveVoc )
        {
                if( GetNetVoc( pWavePlay ) )
                {
                        WriteBuff2Device( pWavePlay );
                }
        }

        return TRUE;
}

BOOL CVocPlay:: PlayDeviceOpen()
{
        BOOL bRtn;
        char szMsg[256];
        MMRESULT mmrRtn;

        m_iClassRef++;
        if( m_hWavePlay != NULL )
        {
                TRACE( "Client %d Play Wave device already open !\n", m_iSenderID );
                return TRUE;
        }

        mmrRtn = waveOutOpen( &m_hWavePlay, WAVE_MAPPER, &m_wfx, (DWORD)(waveOutProc), (DWORD)this, CALLBACK_FUNCTION);
        bRtn = (mmrRtn == MMSYSERR_NOERROR);
        if( bRtn )
        {
                TRACE( "Client %d Play Record Wave device suceess !\n", m_iSenderID );
        }
        else
        {
                waveOutGetErrorText( mmrRtn, szMsg, 256);
                TRACE( szMsg );
                TRACE( " Client %d Play Record Wave device failed !\n", m_iSenderID );
        }
        return ( bRtn );
}

void CVocPlay:: PlayDeviceClose()
{
        m_bPlayVoc = FALSE;
        while( m_bHaveVoc )
        {
                Sleep( 100 );
        }
        m_iClassRef--;
        if( m_iClassRef <= 0 )
        {
                if( m_hWavePlay != NULL )
                {
                        Sleep( 100 );
                        waveOutReset(m_hWavePlay);
                        waveOutClose(m_hWavePlay);
                }
                m_hWavePlay = NULL;
        }
}

BOOL CVocPlay::WriteBuff2Device(WAVEHDR *pWave)
{
        char szMsg[256];

        MMRESULT mmrRtn = waveOutPrepareHeader( m_hWavePlay, pWave, sizeof(WAVEHDR));
        if( mmrRtn != MMSYSERR_NOERROR)
        {
                waveOutGetErrorText( mmrRtn, szMsg, 256);
                TRACE( szMsg );
                delete [] pWave;
                return FALSE;
        }
        mmrRtn = waveOutWrite( m_hWavePlay, pWave, sizeof (WAVEHDR)); //填入新的缓冲
        if( mmrRtn != MMSYSERR_NOERROR)
        {
                waveOutGetErrorText( mmrRtn, szMsg, 256);
                TRACE( szMsg );
                delete [] pWave;
                return FALSE;
        }
        m_bHaveVoc = TRUE;
        return TRUE;
}

void CALLBACK CVocPlay::waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) //放音
{
        WAVEHDR * pWave;
        CVocPlay * pAudio;

        if( uMsg == WOM_DONE )
        {
                pWave = (WAVEHDR *)dwParam1;
                pAudio = (CVocPlay *)pWave->dwUser;
                waveOutUnprepareHeader( hwo, (WAVEHDR *)dwParam1, sizeof(WAVEHDR));
                delete [] (BYTE *)dwParam1;


                if( pAudio->m_bPlayVoc )
                {
                        if( pAudio->GetNetVoc( pWave ) )
                        {
                                pAudio->WriteBuff2Device( pWave );
                        }
                        else
                        {
                                pAudio->m_bHaveVoc = FALSE;
                        }
                }
                else
                {
                        pAudio->CleanVocBuff();
                        pAudio->m_bHaveVoc = FALSE;
                }
        }
}

BOOL CVocPlay::GetNetVoc( WAVEHDR * &pWave )////取网络收到的数据
{
        int iRtn;
        BOOL bRtn;
        WAVEHDR * pMp3Wave;

        bRtn = FALSE;
        pWave = NULL;

        CSingleLock sl(&m_csRecvVocList);
        sl.Lock();

        if( m_listRecvVoc.GetCount() > 0 )
        {
                pMp3Wave = (WAVEHDR *)m_listRecvVoc.RemoveHead();
                if(        pMp3Wave->dwUser == VOC_NET_FORMAT_MP3 )
                {
                        bRtn = TRUE;
                       
                        iRtn = lame_decode( (UCHAR *)pMp3Wave->lpData, pMp3Wave->dwBufferLength,
                                (SHORT *)m_pMp3WaveBuff, (SHORT *)m_pMp3WaveBuff );
                        if( iRtn > 0 )
                        {
                                pWave = (WAVEHDR *) new BYTE[iRtn +sizeof(WAVEHDR)];

                                pWave->dwFlags = WHDR_DONE;
                                pWave->dwBufferLength = iRtn;
                                pWave->dwUser = (DWORD)this;
                                pWave->lpData = (char *)((BYTE *)pWave + sizeof(WAVEHDR));
                                CopyMemory( pWave->lpData, m_pMp3WaveBuff, iRtn );
                        }

                }
                else
                {
                        TRACE("Recv Unknow net voc format %d \n", pWave->dwUser);
                        delete [] pMp3Wave;
                        pWave = NULL;
                }
        }
        sl.Unlock();

        return bRtn;
}

void CVocPlay::CleanVocBuff()
{
        void * p;

        CSingleLock sl(&m_csRecvVocList);
        sl.Lock();
        for( ; m_listRecvVoc.GetCount() > 0 ; )
        {
                p = m_listRecvVoc.RemoveHead();
                delete [] p;
        }
        sl.Unlock();
}

[ 本帖最后由 ganjike 于 2007-4-23 11:27 编辑 ]
 楼主| 发表于 2007-4-23 15:45:52 | 显示全部楼层
收到!谢谢!

     根据你的提示,从网上找到了wave API的典型应用和说明。

     用wave的AP函数做的输出模块。自己做了两个滑块控件,一个用来实时改变波形的幅值、频率。一个用来控制输出强度(音量)。

     现在就差把波形实时的显示出来了。

     “搏死”还不知道,先歇两天再给他!
发表于 2007-4-27 17:55:37 | 显示全部楼层
Ganjike老大真是大好人!
发表于 2007-5-2 09:33:23 | 显示全部楼层
只是入行比较早,稍微多知道点儿东西而已。
不算什么。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|蒙古论坛

GMT+8, 2026-7-15 16:38 , Processed in 0.013002 second(s), 16 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表