带有一个wave的简单Waveout API [英] Simple Waveout API with one wave

查看:90
本文介绍了带有一个wave的简单Waveout API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

亲爱的朋友们,

我使用C ++进行编程,并且在我的PC上运行waveout API时遇到问题。任何人都可以帮助我获得正确的代码以使其正常工作吗?我正在使用VSC ++ Express!我已经包含了stdio.h,windows.h和winmm.lib!我会饶有帮助!





Dear friends,
I am programming in C++ and have a problem with waveout API to run on my PC. Could anybody help me to get the code right to get it work properly please ? I am using VSC++ Express! I have included stdio.h, windows.h, and winmm.lib ! I will apreciated evry help !


#define SOUNDBUFF 65536;
WAVEFORMATEX wf;
WAVEHDR whdr;
HWAVEOUT hWaveOut;
LPSTR lpData;
float clpData[65536];
 
int main(void)
{
 
FILE *f = fopen("c:/JP8080.wav","rb")
fwrite(&clpdata, 2, 1, sizeof(clpdata), f);
 
wf.wFormatTag=WAVE_FORMAT_PCM;
wf.nChannels=2;
wf.nSamplesPerSec=44100;
wf.nAvgBytesPerSec=(44100*4);
wf.nBlockAlign=(2*16)/8;
wf.wBitsPerSample=16;
wf.cbSize=0;

whdr.lpData = clpData;
whdr.dwBufferLength = SOUNDBUFF;
whdr.dwFlags = 0;
whdr.dwLoops = 0;
 
do {
} while (!(whdr.dwFlags & WHDR_DONE));
 
waveOutOpen(&hWaveOut,WAVE_MAPPER,&wf,0,0,CALLBACK_NULL);
waveOutPrepareHeader(hWaveOut,&whdr,sizeof(whdr));
waveOutWrite(hWaveOut,&whdr,sizeof(whdr));
 
do {
} while (!(whdr.dwFlags & WHDR_DONE));
 
waveOutUnprepareHeader(hWaveOut,&whdr,sizeof(whdr));
waveOutClose(hWaveOut);
 
return 0;
}

推荐答案

在我写任何其他内容之前,请允许我说明这是一个如何不代码的完美示例! ! (但它确实对我测试过的2个文件起作用 - 令人惊讶的是)



我写这篇文章的方式和我16岁的时候写的一样 - 它是所有的狗'鸟'粗糙粗糙,便宜 - 便宜



我应该注意到需要一个空的while while循环。 - 我们只是不断轮询WaveOutWrite是否在wh.dwFlags中设置了WHDR_DONE位





但是,你应该知道WAV格式不仅仅包含原始数据 - 它包含播放所需的信息,它还可能包括压缩和许多其他内容。



我鞭打这个使用: http://www.sonicspot.com/guide/wavefiles.html [ ^ ]

当然,MSDN ..



此代码是在使用Win7的系统上创建的。请相应地调整wav文件的路径。







Before I write anything else, let me state that this is a perfect example of HOW NOT TO CODE!! (but it does function for the 2 files I tested with - surprisingly)

I've written this in much the same way I wrote everything when I was 16 - it's all Dog 'n' Bird..... Rough-Rough, Cheap-Cheap

I should note that 1 of the empty do while loops IS needed. - We're just continually polling to see if WaveOutWrite has set the WHDR_DONE bit in wh.dwFlags


However, you should be aware that the WAV format holds so much more than just raw data - it holds information needed for playback, it may also include compression and a plethora of other things.

I whipped this up using: http://www.sonicspot.com/guide/wavefiles.html[^]
And of course, MSDN..

This code is created on a system with Win7. Please, adjust the path to the wav file accordingly.



#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>

typedef struct wavFileHeader
{
    long chunkId;           //"RIFF" (0x52,0x49,0x46,0x46)
    long chunkSize;         // (fileSize - 8)  - could also be thought of as bytes of data in file following this field (bytesRemaining)
    long riffType;          // "WAVE" (0x57415645)
};

typedef struct fmtChunk
{
    long chunkId;                       // "fmt " - (0x666D7420)
    long chunkDataSize;                 // 16 + extra format bytes
    short compressionCode;              // 1 - 65535
    short numChannels;                  // 1 - 65535
    long sampleRate;                    // 1 - 0xFFFFFFFF
    long avgBytesPerSec;                // 1 - 0xFFFFFFFF
    short blockAlign;                   // 1 - 65535
    short significantBitsPerSample;     // 2 - 65535
    short extraFormatBytes;             // 0 - 65535
};

typedef struct wavChunk
{
    long chunkId;
    long chunkDataSize;
};



char *readFileData(char *szFilename, long &dataLengthOut)
{
    FILE *fp = fopen(szFilename, "rb");
    long len;
    char *buffer;
    fseek(fp, 0, SEEK_END);
    len = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    buffer = (char*) calloc(1, len+1);
    fread(buffer, 1, len, fp);
    fclose(fp);
    dataLengthOut = len;
    return buffer;
}

void parseWav(char *data)
{
    long *mPtr;
    void *tmpPtr;

    char *buffer;

    WAVEFORMATEX wf;
    WAVEHDR wh;
    HWAVEOUT hWaveOut;

    fmtChunk mFmtChunk;
    wavChunk mDataChunk;

    mPtr = (long*)data;

    if ( mPtr[0] == 0x46464952) //  little endian check for 'RIFF'
    {
        mPtr += 3;
        if (mPtr[0] == 0x20746D66)  // little endian for "fmt "
        {
           // printf("Format chunk found\n");

            tmpPtr = mPtr;
            memcpy(&mFmtChunk, tmpPtr, sizeof(mFmtChunk));
            tmpPtr += 8;
            tmpPtr += mFmtChunk.chunkDataSize;

            mPtr = (long*)tmpPtr;
            if (mPtr[0] == 0x61746164)        // little endian for "data"
            {
            //    printf("Data chunk found\n");

                tmpPtr = mPtr;
                memcpy(&mDataChunk, tmpPtr, sizeof(mDataChunk));
                mPtr += 2;

                buffer = (char*) malloc(mDataChunk.chunkDataSize);
                memcpy(buffer, mPtr, mDataChunk.chunkDataSize);

                printf("sampleRate: %d\n", mFmtChunk.sampleRate);

                wf.wFormatTag = mFmtChunk.compressionCode;
                wf.nChannels = mFmtChunk.numChannels;
                wf.nSamplesPerSec = mFmtChunk.sampleRate;
                wf.nAvgBytesPerSec = mFmtChunk.avgBytesPerSec;
                wf.nBlockAlign = mFmtChunk.blockAlign;
                wf.wBitsPerSample = mFmtChunk.significantBitsPerSample;
                wf.cbSize = mFmtChunk.extraFormatBytes;

                wh.lpData = buffer;
                wh.dwBufferLength = mDataChunk.chunkDataSize;
                wh.dwFlags = 0;
                wh.dwLoops = 0;

                waveOutOpen(&hWaveOut,WAVE_MAPPER,&wf,0,0,CALLBACK_NULL);
                waveOutPrepareHeader(hWaveOut,&wh,sizeof(wh));
                waveOutWrite(hWaveOut,&wh,sizeof(wh));

                do {}
                while (!(wh.dwFlags & WHDR_DONE));

                waveOutUnprepareHeader(hWaveOut,&wh,sizeof(wh));
                waveOutClose(hWaveOut);

                free(buffer);
            }
        }

    }

    else
        printf("INvalid WAV\n");
}


int main()
{
    char *filename = "c:/windows/media/tada.wav";
    char *buffer;
    long fileSize;

    buffer = readFileData(filename, fileSize);
    parseWav(buffer);

    free(buffer);

    return 0;
}







编辑:我刚刚玩了这个代码,发现了很多我的恐怖 - 在发布版本运行后播放声音时程序挂起 - (从未将其作为调试版本翻过来)



似乎编译器正在优化空的do while循环 - 没有意识到我的源代码之外的代码将修改wh.dwFlags



解决方案是这样添加volatile关键字:




I just played with this code some more, discovering much to my horror - that the program hung after playing the sound when the release version was run -(never flicked it over from being a debug build)

It seems that the compiler was optimizing the empty do while loop - not realizing that code outside of my source was going to modify wh.dwFlags

The solution was to add the volatile keyword thusly:

volatile WAVEHDR wh;



和任何使用& wh的用法如下:


and to cast any use of &wh like so:

(wavehdr_tag*)&wh


此代码已有近4年的历史,但我很满意。它是WaveOut函数的第一个例子,我可以开始工作。



我需要另外修改才能完成这项工作。

一些.wav文件有一个我们需要跳过的信息块。

我必须在数据(0x61746164)的测试前插入这段代码:



This code is nearly 4 years old already, but I am pleased with it. Its the first example with WaveOut functions that I could get to work.

I needed another modification to make this work.
Some .wav files have an info block that we need to skip.
I had to insert this code just in front of the test for "data" (0x61746164):

if (mPtr[0] == 0x5453494C) {       // little endian for "LIST"
    // skip info chunk
    memcpy(&mDataChunk, tmpPtr, sizeof(mDataChunk));
    tmpPtr = (void*) (((char*) tmpPtr ) + 8 + mDataChunk.chunkDataSize);
    mPtr = (long*)tmpPtr;
}

if (mPtr[0] == 0x61746164)





我的编译器( Borland CBuilder 6)抱怨这一行的语法:



Also my compiler (Borland CBuilder 6) complained about the syntax of this line:

tmpPtr += 8;



我必须将其更改为:


I had to change it to:

tmpPtr = (void*) ((char*) tmpPtr ) + 8;


这篇关于带有一个wave的简单Waveout API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆