• R/O
  • HTTP
  • SSH
  • HTTPS

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

oga's tools


File Info

Rev. 2b80abcdeb00aad07aa265bd434df3975aadbb9a
크기 11,371 bytes
Time 2024-12-10 04:54:07
Author hyperoga
Log Message

add color() func

Content

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

void play1(char *media_file)
{
    int  play_flag = SND_SYNC;

    printf("playing by sndPlaySound()...\n");
    sndPlaySound(media_file, play_flag);
    
}

void play2(char *media_file)
{
    //int  play_flag = SND_APPLICATION | SND_SYNC;
    int  play_flag = SND_SYNC;

    printf("playing by PlaySound()...\n");
    PlaySound(media_file,
              NULL, 
	      SND_FILENAME | play_flag);
}

// ### play3 start
#define OUTPUT_BUFFER_NUM   3       //再生ギャップを起こさないために2以上にする
#define OUTPUT_BUFFER_SIZE  0x8000  //処理が間に合わないならば大きくする
#define dprintf printf
LPWAVEHDR  g_OutputBuffer[OUTPUT_BUFFER_NUM];
HWAVEOUT   g_hwo;
FILE       *g_fp;
int        g_nBuffUseNum;
int        g_nBuffSetPos;
int        g_playing  = 0;
int        g_rsize    = 0;
int        g_total    = 0;


//再生バッファ確保
BOOL AllocOutputBuffer()
{
    int i;
    for(i = 0 ; i < OUTPUT_BUFFER_NUM ; i++){
        g_OutputBuffer[i]
            = (LPWAVEHDR) HeapAlloc(GetProcessHeap(), 
                                    HEAP_ZERO_MEMORY, 
                                    sizeof(WAVEHDR));
        if(g_OutputBuffer[i]){
            g_OutputBuffer[i]->lpData
                = (LPSTR) HeapAlloc(GetProcessHeap(), 
		                    HEAP_ZERO_MEMORY, 
				    OUTPUT_BUFFER_SIZE);
            if(g_OutputBuffer[i]->lpData) {
                g_OutputBuffer[i]->dwBufferLength = OUTPUT_BUFFER_SIZE;
	    }
        }
    }
    g_nBuffSetPos = g_nBuffUseNum = 0;
    return TRUE;
}

//再生バッファ開放
void FreeOutputBuffer()
{
    int i;
    for(i = 0 ; i < OUTPUT_BUFFER_NUM ; i++){
        if(g_OutputBuffer[i]){
            if(g_OutputBuffer[i]->lpData) {
                HeapFree(GetProcessHeap(), 0, g_OutputBuffer[i]->lpData);
	    }
            HeapFree(GetProcessHeap(), 0, g_OutputBuffer[i]);
            g_OutputBuffer[i] = NULL;
        }
    }
}

//データをバッファに読みこんで再生デバイスに送信
void    FillBuffer(HWAVEOUT hwo, FILE *fp)
{
    MMRESULT    mmRes;
    WAVEHDR*    pHdr;
    int         size;

    while(g_nBuffUseNum < OUTPUT_BUFFER_NUM) {
        pHdr = g_OutputBuffer[g_nBuffSetPos];

	dprintf("DEBUG: read wav to #%d buff\n", g_nBuffSetPos);

        size = fread(pHdr->lpData, 1, OUTPUT_BUFFER_SIZE, fp);
        if (size == 0) {
	    dprintf("DEBUG: no more data. g_nBuffUseNum = %d\n", g_nBuffUseNum);
	    break;
        }

        pHdr->dwBufferLength = size;

	g_rsize += size;
	dprintf("DEBUG: read size %d   %3d%% (%d/%d)KB\n", size,
	                               g_rsize/(g_total/100),
				       g_rsize/1024,
				       g_total/1024);

        mmRes = waveOutPrepareHeader(hwo, pHdr, sizeof(WAVEHDR));
        if(mmRes != MMSYSERR_NOERROR){
            dprintf("Error in FillBuffer\n");
            break;
        }
        mmRes = waveOutWrite(hwo, pHdr, sizeof(WAVEHDR));
        if(mmRes != MMSYSERR_NOERROR){
            dprintf("Error in FillBuffer\n");
            break;
        }
	g_playing = 1;

        g_nBuffSetPos = (g_nBuffSetPos + 1) % OUTPUT_BUFFER_NUM;
        g_nBuffUseNum++;
    }

    return;
}


// コールバック関数  
void CALLBACK waveOutCallBack(HWAVEOUT hwo, 
                              UINT uMsg,
			      DWORD dwInstance, 
			      DWORD dwParam1, 
			      DWORD dwParam2)
{
    switch(uMsg) {
      case WOM_OPEN:
        // デバイスOpen
	dprintf("WOM_OPEN event!\n");
        break;

      case WOM_CLOSE:
        // デバイスClose
	dprintf("WOM_CLOSE event!\n");
        break;

      case WOM_DONE:
        // データブロック再生終了
	{
	    int i;
	    LPWAVEHDR pwh = (LPWAVEHDR)dwParam1;
	    dprintf("WOM_DONE event!\n");

            //使用中バッファ数を一つ開放
            g_nBuffUseNum--;

	    FillBuffer(hwo, g_fp);

	    dprintf("WOM_DONE event! (g_nBuffUseNum:%d)\n", g_nBuffUseNum);
	    if (g_nBuffUseNum == 0){
	        // 再生終了 
                // データブロックの非準備状態へ
	        dprintf("Play done!\n");
		g_playing = 0;
	    }
	}
        break;
    }
}

/* data formats */
typedef struct riff_hdr {
    char          id[4];           /* RIFF id   ("RIFF")        */
    unsigned long len;             /* length                    */
    char          wave_id[4];      /* data type ("WAVE")        */
} riff_hdr_t;

typedef struct chunk_hdr {
    char          id[4];           /* chunk id  ("fmt "|"data"...) */
    unsigned long len;             /* chunk length                 */
} chunk_hdr_t;

/* chunk type fmt  1 */
typedef struct ck_fmt {
    unsigned short wFormatTag;        /* Format category       */
    unsigned short wChannels;         /* Number of channels    */
    unsigned long  dwSamplesPerSec;   /* Sampling rate         */
    unsigned long  dwAvgBytesPerSec;  /* For buffer estimation */
    unsigned short wBlockAlign;       /* Data block size       */
    unsigned short wBitsPerSample;    /* Sample size (for WAVE_FORMAT_PCM */
    unsigned short unknown;           /* Unknown data                     */
    char dummy[256];                  /* dummy area for over run */
} ck_fmt_t;

/* chunk type fact 2 */
typedef struct ck_fact {
    int  unknown;               /* unknown */
} ck_fact_t;

int GetWaveFormat(FILE *fp, WAVEFORMATEX *pwfx)
{
    riff_hdr_t  riffhdr;
    chunk_hdr_t chunkhdr;
    char        buf_fmt[4096];
    char        buf_fact[4096];
    int         size;

    ck_fmt_t  *ckfmt  = (ck_fmt_t *)buf_fmt;
    ck_fact_t *ckfact = (ck_fact_t *)buf_fact;

    // Read WAV Header
    fread(&riffhdr, sizeof(riffhdr), 1, fp);
    if (memcmp(riffhdr.id, "RIFF", 4)) {
        dprintf("not RIFF format\n");
	return -1;
    }

    // Read Chunk Header
    while (1) {
        size = fread(&chunkhdr, 1, sizeof(chunkhdr), fp);
	if (size <= 0) {
            dprintf("Fmt Chunk Not Found Error\n");
	    return -1;
	}
	if (!strncmp(chunkhdr.id, "fmt", 3)) {
	    // WAVフォーマットチャンク(fmt)発見 
            // Read Fmt Chunk Header
            size = fread(ckfmt, 1, chunkhdr.len, fp);
            if (size != chunkhdr.len) {
                dprintf("Fmt Chunk Read Error\n");
        	return -1;
            }

            // Stereo 16bit 44kHz
            //wfx.wFormatTag      = WAVE_FORMAT_PCM;
            //wfx.nChannels       = 2;
            //wfx.nSamplesPerSec  = 44100;
            //wfx.wBitsPerSample  = 16;
            //wfx.nBlockAlign     = wfx.nChannels * wfx.wBitsPerSample/8;
            //wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
            //wfx.cbSize          = 0;

            pwfx->wFormatTag      = ckfmt->wFormatTag;
            pwfx->nChannels       = ckfmt->wChannels;
            pwfx->nSamplesPerSec  = ckfmt->dwSamplesPerSec;
            pwfx->wBitsPerSample  = ckfmt->wBitsPerSample;
            pwfx->nBlockAlign     = ckfmt->wBlockAlign;
            pwfx->nAvgBytesPerSec = ckfmt->dwAvgBytesPerSec;
            pwfx->cbSize          = 0;

            dprintf("---- fmt chunk (len=%d) ----\n", chunkhdr.len);
            dprintf("FormatTag      : 0x%04x     (%d) %s\n",ckfmt->wFormatTag, 
                                                   ckfmt->wFormatTag,
                    (ckfmt->wFormatTag == WAVE_FORMAT_PCM)?"MS PCM":"Other PCM");
            dprintf("Channels       : 0x%04x     (%d) %s\n",ckfmt->wChannels, 
                                                   ckfmt->wChannels,
                    (ckfmt->wChannels == 1)?"Mono":"Stereo");
            dprintf("SamplesPerSec  : 0x%08x (%d)\n",ckfmt->dwSamplesPerSec, 
                                            ckfmt->dwSamplesPerSec);
            dprintf("AvgBytesPerSec : 0x%08x (%d)\n",ckfmt->dwAvgBytesPerSec, 
                                            ckfmt->dwAvgBytesPerSec);
            dprintf("BlockAlign     : 0x%04x     (%d)\n",ckfmt->wBlockAlign, 
                                                ckfmt->wBlockAlign);
            dprintf("BitsPerSample  : 0x%04x     (%d bits)\n",ckfmt->wBitsPerSample, 
                                                     ckfmt->wBitsPerSample);

	} else if (!strncmp(chunkhdr.id, "fact", 4)) {
	    // FACTチャンク(fact)は空読み 
            fread(ckfact, chunkhdr.len, 1, fp);
	} else if (!strncmp(chunkhdr.id, "data", 4)) {
	    // DATAチャンク(data)発見
	    // DATAブロックの先頭位置に位置付けてこの関数は終了 
	    dprintf("data chunk found. len = %d\n", chunkhdr.len);
	    g_total = chunkhdr.len;
	    break;
	}
    };

    return 0;
}

void play3(char *media_file)
{
    MMRESULT     mmRes;
    WAVEFORMATEX wfx;
    int          size;
    int          i;

    // Stereo 16bit 44kHz
    //wfx.wFormatTag      = WAVE_FORMAT_PCM;
    //wfx.nChannels       = 2;
    //wfx.nSamplesPerSec  = 44100;
    //wfx.wBitsPerSample  = 16;
    //wfx.nBlockAlign     = wfx.nChannels * wfx.wBitsPerSample/8;
    //wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
    //wfx.cbSize          = 0;

    // open wav
    if ((g_fp = fopen(media_file, "rb")) == NULL) {
        perror(media_file);
        return;
    }

    // get wav format
    if (GetWaveFormat(g_fp, &wfx) < 0) {
        dprintf("Wave Format Error. %s\n", media_file);
        return;
    }

    mmRes = waveOutOpen(&g_hwo,
                        WAVE_MAPPER,
		        &wfx,
		        (DWORD)(LPVOID)waveOutCallBack,
		        0,
		        CALLBACK_FUNCTION);
    if (mmRes != MMSYSERR_NOERROR) {
        dprintf("waveOutOpen Error %d\n", mmRes);
        exit(1);
    }

    AllocOutputBuffer();

    // wav読み込み & デバイス書き込み要求 
    FillBuffer(g_hwo, g_fp);

    // すべて再生されるまで待つ  
    while (g_playing) {
        Sleep(500);
    }

    // データブロックの非準備状態へ
    for(i = 0 ; i < OUTPUT_BUFFER_NUM ; i++) {
        waveOutUnprepareHeader(g_hwo, 
                               g_OutputBuffer[i], 
                               sizeof(WAVEHDR));
    }

    //再生デバイスをクローズ
    dprintf("DEBUG: waveOutClose()\n");
    waveOutClose(g_hwo);

    //再生バッファを開放
    dprintf("DEBUG: FreeOutputBuffer()\n");
    FreeOutputBuffer();

    //WAVファイルクローズ 
    dprintf("DEBUG: fclose()\n");
    fclose(g_fp);
}
// ### play3 end

int main(int a, char *b[])
{
    int  i;
    int  play_type = 3;
    char *media_file = "I:\\WINNT\\Media\\ringin.wav";

    for (i=1; i<a; i++) {
        if (!strcmp(b[i], "-h")) {
            printf("usage: play [{-1|-2|<-3>}] [media_file]\n");
	    printf("    -1 : sndPlaySound()\n");
	    printf("    -2 : PlaySound()\n");
	    printf("    -3 : waveOutWrite()  (default)\n");
	    exit(1);
        }
        if (!strcmp(b[i], "-1")) {
	    play_type = 1;
	    continue;
	}
        if (!strcmp(b[i], "-2")) {
	    play_type = 2;
	    continue;
	}
        if (!strcmp(b[i], "-3")) {
	    play_type = 3;
	    continue;
	}
        media_file = b[i];
    }

    switch (play_type) {
      case 1:
        play1(media_file);
	break;
      case 2:
        play2(media_file);
	break;
      case 3:
        play3(media_file);
	break;
    }

    return 0;
}