?? wildmidi.c
字號:
/* wildmidi.c Midi Player using the WildMidi Midi Processing Library Copyright (C)2001-2004 Chris Ison This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Email: cisos@bigpond.net.au wildcode@users.sourceforge.net $Id: wildmidi.c,v 1.21 2004/01/28 05:45:09 wildcode Exp $*/#include "config.h"#include <errno.h>#include <fcntl.h>#include <getopt.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifndef _WIN32#include <termios.h>#include <sys/ioctl.h>#include <sys/mman.h>#endif#include <sys/stat.h>#include <sys/types.h>#include <unistd.h>#if (defined _WIN32) || (defined __CYGWIN__)# include <conio.h># include <windows.h># include <mmsystem.h>#else# ifdef HAVE_ALSA# include <alsa/asoundlib.h># else# ifdef HAVE_SYS_SOUNDCARD_H# include <sys/soundcard.h># elif defined HAVE_LINUX_SOUNDCARD_H# include <linux/soundcard.h># elif HAVE_MACHINE_SOUNDCARD_H# include <machine/soundcard.h># endif# endif#endif#include "wildmidi_lib.h"#ifndef FNONBLOCK#define FNONBLOCK _FNONBLOCK#endifstruct _midi_test { unsigned char *data; unsigned long int size;};// scale test from 0 to 127/* test a * offset 18-21 (0x12-0x15) - track size * offset 25 (0x1A) = bank number * offset 28 (0x1D) = patch number */ unsigned char midi_test_c_scale[] = { 0x4d, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, // 0x00 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x4d, 0x54, // 0x08 0x72, 0x6b, 0x00, 0x00, 0x02, 0x63, 0x00, 0xb0, // 0x10 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x90, 0x00, // 0x18 C 0x64, 0x08, 0x80, 0x00, 0x00, 0x08, 0x90, 0x02, // 0x20 D 0x64, 0x08, 0x80, 0x02, 0x00, 0x08, 0x90, 0x04, // 0x28 E 0x64, 0x08, 0x80, 0x04, 0x00, 0x08, 0x90, 0x05, // 0x30 F 0x64, 0x08, 0x80, 0x05, 0x00, 0x08, 0x90, 0x07, // 0x38 G 0x64, 0x08, 0x80, 0x07, 0x00, 0x08, 0x90, 0x09, // 0x40 A 0x64, 0x08, 0x80, 0x09, 0x00, 0x08, 0x90, 0x0b, // 0x48 B 0x64, 0x08, 0x80, 0x0b, 0x00, 0x08, 0x90, 0x0c, // 0x50 C 0x64, 0x08, 0x80, 0x0c, 0x00, 0x08, 0x90, 0x0e, // 0x58 D 0x64, 0x08, 0x80, 0x0e, 0x00, 0x08, 0x90, 0x10, // 0x60 E 0x64, 0x08, 0x80, 0x10, 0x00, 0x08, 0x90, 0x11, // 0x68 F 0x64, 0x08, 0x80, 0x11, 0x00, 0x08, 0x90, 0x13, // 0x70 G 0x64, 0x08, 0x80, 0x13, 0x00, 0x08, 0x90, 0x15, // 0x78 A 0x64, 0x08, 0x80, 0x15, 0x00, 0x08, 0x90, 0x17, // 0x80 B 0x64, 0x08, 0x80, 0x17, 0x00, 0x08, 0x90, 0x18, // 0x88 C 0x64, 0x08, 0x80, 0x18, 0x00, 0x08, 0x90, 0x1a, // 0x90 D 0x64, 0x08, 0x80, 0x1a, 0x00, 0x08, 0x90, 0x1c, // 0x98 E 0x64, 0x08, 0x80, 0x1c, 0x00, 0x08, 0x90, 0x1d, // 0xA0 F 0x64, 0x08, 0x80, 0x1d, 0x00, 0x08, 0x90, 0x1f, // 0xA8 G 0x64, 0x08, 0x80, 0x1f, 0x00, 0x08, 0x90, 0x21, // 0xB0 A 0x64, 0x08, 0x80, 0x21, 0x00, 0x08, 0x90, 0x23, // 0xB8 B 0x64, 0x08, 0x80, 0x23, 0x00, 0x08, 0x90, 0x24, // 0xC0 C 0x64, 0x08, 0x80, 0x24, 0x00, 0x08, 0x90, 0x26, // 0xC8 D 0x64, 0x08, 0x80, 0x26, 0x00, 0x08, 0x90, 0x28, // 0xD0 E 0x64, 0x08, 0x80, 0x28, 0x00, 0x08, 0x90, 0x29, // 0xD8 F 0x64, 0x08, 0x80, 0x29, 0x00, 0x08, 0x90, 0x2b, // 0xE0 G 0x64, 0x08, 0x80, 0x2b, 0x00, 0x08, 0x90, 0x2d, // 0xE8 A 0x64, 0x08, 0x80, 0x2d, 0x00, 0x08, 0x90, 0x2f, // 0xF0 B 0x64, 0x08, 0x80, 0x2f, 0x00, 0x08, 0x90, 0x30, // 0xF8 C 0x64, 0x08, 0x80, 0x30, 0x00, 0x08, 0x90, 0x32, // 0x100 D 0x64, 0x08, 0x80, 0x32, 0x00, 0x08, 0x90, 0x34, // 0x108 E 0x64, 0x08, 0x80, 0x34, 0x00, 0x08, 0x90, 0x35, // 0x110 F 0x64, 0x08, 0x80, 0x35, 0x00, 0x08, 0x90, 0x37, // 0x118 G 0x64, 0x08, 0x80, 0x37, 0x00, 0x08, 0x90, 0x39, // 0x120 A 0x64, 0x08, 0x80, 0x39, 0x00, 0x08, 0x90, 0x3b, // 0X128 B 0x64, 0x08, 0x80, 0x3b, 0x00, 0x08, 0x90, 0x3c, // 0x130 C 0x64, 0x08, 0x80, 0x3c, 0x00, 0x08, 0x90, 0x3e, // 0x138 D 0x64, 0x08, 0x80, 0x3e, 0x00, 0x08, 0x90, 0x40, // 0X140 E 0x64, 0x08, 0x80, 0x40, 0x00, 0x08, 0x90, 0x41, // 0x148 F 0x64, 0x08, 0x80, 0x41, 0x00, 0x08, 0x90, 0x43, // 0x150 G 0x64, 0x08, 0x80, 0x43, 0x00, 0x08, 0x90, 0x45, // 0x158 A 0x64, 0x08, 0x80, 0x45, 0x00, 0x08, 0x90, 0x47, // 0x160 B 0x64, 0x08, 0x80, 0x47, 0x00, 0x08, 0x90, 0x48, // 0x168 C 0x64, 0x08, 0x80, 0x48, 0x00, 0x08, 0x90, 0x4a, // 0x170 D 0x64, 0x08, 0x80, 0x4a, 0x00, 0x08, 0x90, 0x4c, // 0x178 E 0x64, 0x08, 0x80, 0x4c, 0x00, 0x08, 0x90, 0x4d, // 0x180 F 0x64, 0x08, 0x80, 0x4d, 0x00, 0x08, 0x90, 0x4f, // 0x188 G 0x64, 0x08, 0x80, 0x4f, 0x00, 0x08, 0x90, 0x51, // 0x190 A 0x64, 0x08, 0x80, 0x51, 0x00, 0x08, 0x90, 0x53, // 0x198 B 0x64, 0x08, 0x80, 0x53, 0x00, 0x08, 0x90, 0x54, // 0x1A0 C 0x64, 0x08, 0x80, 0x54, 0x00, 0x08, 0x90, 0x56, // 0x1A8 D 0x64, 0x08, 0x80, 0x56, 0x00, 0x08, 0x90, 0x58, // 0x1B0 E 0x64, 0x08, 0x80, 0x58, 0x00, 0x08, 0x90, 0x59, // 0x1B8 F 0x64, 0x08, 0x80, 0x59, 0x00, 0x08, 0x90, 0x5b, // 0x1C0 G 0x64, 0x08, 0x80, 0x5b, 0x00, 0x08, 0x90, 0x5d, // 0x1C8 A 0x64, 0x08, 0x80, 0x5d, 0x00, 0x08, 0x90, 0x5f, // 0x1D0 B 0x64, 0x08, 0x80, 0x5f, 0x00, 0x08, 0x90, 0x60, // 0x1D8 C 0x64, 0x08, 0x80, 0x60, 0x00, 0x08, 0x90, 0x62, // 0x1E0 D 0x64, 0x08, 0x80, 0x62, 0x00, 0x08, 0x90, 0x64, // 0x1E8 E 0x64, 0x08, 0x80, 0x64, 0x00, 0x08, 0x90, 0x65, // 0x1F0 F 0x64, 0x08, 0x80, 0x65, 0x00, 0x08, 0x90, 0x67, // 0x1F8 G 0x64, 0x08, 0x80, 0x67, 0x00, 0x08, 0x90, 0x69, // 0x200 A 0x64, 0x08, 0x80, 0x69, 0x00, 0x08, 0x90, 0x6b, // 0x208 B 0x64, 0x08, 0x80, 0x6b, 0x00, 0x08, 0x90, 0x6c, // 0x210 C 0x64, 0x08, 0x80, 0x6c, 0x00, 0x08, 0x90, 0x6e, // 0x218 D 0x64, 0x08, 0x80, 0x6e, 0x00, 0x08, 0x90, 0x70, // 0x220 E 0x64, 0x08, 0x80, 0x70, 0x00, 0x08, 0x90, 0x71, // 0x228 F 0x64, 0x08, 0x80, 0x71, 0x00, 0x08, 0x90, 0x73, // 0x230 G 0x64, 0x08, 0x80, 0x73, 0x00, 0x08, 0x90, 0x75, // 0x238 A 0x64, 0x08, 0x80, 0x75, 0x00, 0x08, 0x90, 0x77, // 0x240 B 0x64, 0x08, 0x80, 0x77, 0x00, 0x08, 0x90, 0x78, // 0x248 C 0x64, 0x08, 0x80, 0x78, 0x00, 0x08, 0x90, 0x7a, // 0x250 D 0x64, 0x08, 0x80, 0x7a, 0x00, 0x08, 0x90, 0x7c, // 0x258 E 0x64, 0x08, 0x80, 0x7c, 0x00, 0x08, 0x90, 0x7d, // 0x260 F 0x64, 0x08, 0x80, 0x7d, 0x00, 0x08, 0x90, 0x7f, // 0x268 G 0x64, 0x08, 0x80, 0x7f, 0x00, 0x08, 0xff, 0x2f, // 0x270 0x00 // 0x278};struct _midi_test midi_test[]= { {midi_test_c_scale, 663}, {NULL, 0}};int midi_test_max = 1;/* ============================== Audio Output Functions ------------------------------ ==============================*/unsigned int rate = 32072;char *pcmname = NULL;int (*send_output) (char * output_data, int output_size);void (*close_output) ( void );int audio_fd;inline voidshutdown_output ( void ) { printf("Shutting Down Sound System\n"); if (audio_fd != -1) close(audio_fd);}/* Wav Output Functions*/static char wav_file[1024] = "\0";unsigned long int wav_size;int write_wav_output (char * output_data, int output_size);void close_wav_output ( void );intopen_wav_output ( void ) { char wav_hdr[] = { 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x10, 0xB1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00 }; if (wav_file[0] == '\0') return -1;#ifdef _WIN32 if ((audio_fd = open(wav_file, (O_RDWR | O_CREAT | O_TRUNC | O_BINARY))) < 0) {#else if ((audio_fd = open(wav_file, (O_RDWR | O_CREAT | O_TRUNC), (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))) < 0) {#endif return -1; } else { unsigned long int bytes_per_sec; wav_hdr[24] = (rate) & 0xFF; wav_hdr[25] = (rate >> 8) & 0xFF; bytes_per_sec = rate * 4; wav_hdr[28] = (bytes_per_sec) & 0xFF; wav_hdr[29] = (bytes_per_sec >> 8) & 0xFF; wav_hdr[30] = (bytes_per_sec >> 16) & 0xFF; wav_hdr[31] = (bytes_per_sec >> 24) & 0xFF; } if (write(audio_fd, &wav_hdr, 44) < 0) { printf("ERROR: Writing Header %s\n", strerror(errno)); shutdown_output(); return -1; } wav_size = 0; send_output = write_wav_output; close_output = close_wav_output; return 0;}intwrite_wav_output (char * output_data, int output_size) { if (write(audio_fd, output_data, output_size) < 0) { printf("ERROR: Writing Wav %s\n", strerror(errno)); shutdown_output(); return -1; } wav_size += output_size; return 0;}voidclose_wav_output ( void ) { char wav_count[4]; if (audio_fd == -1) return; wav_count[0] = (wav_size) & 0xFF; wav_count[1] = (wav_size >> 8) & 0xFF; wav_count[2] = (wav_size >> 16) & 0xFF; wav_count[3] = (wav_size >> 24) & 0xFF; lseek(audio_fd,40,SEEK_SET); write(audio_fd,&wav_count,4); wav_size += 36; wav_count[0] = (wav_size) & 0xFF; wav_count[1] = (wav_size >> 8) & 0xFF; wav_count[2] = (wav_size >> 16) & 0xFF; wav_count[3] = (wav_size >> 24) & 0xFF; lseek(audio_fd,4,SEEK_SET); write(audio_fd,&wav_count,4); shutdown_output();}#if (defined _WIN32) || (defined __CYGWIN__)HWAVEOUT hWaveOut;WAVEHDR header; unsigned long int mm_buffer_count;static CRITICAL_SECTION waveCriticalSection; int write_mm_output (char * output_data, int output_size);void close_mm_output ( void );WAVEHDR *mm_blocks;#define MM_BLOCK_SIZE 16384#define MM_BLOCK_COUNT 3unsigned long int mm_free_blocks = MM_BLOCK_COUNT;unsigned long int mm_current_block = 0;static void CALLBACK mmOutProc( HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) { int* freeBlockCounter = (int*)dwInstance; if(uMsg != WOM_DONE) return; EnterCriticalSection(&waveCriticalSection); (*freeBlockCounter)++; LeaveCriticalSection(&waveCriticalSection); } intopen_mm_output ( void ) { WAVEFORMATEX wfx; char *mm_buffer; int i; InitializeCriticalSection(&waveCriticalSection); if((mm_buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, ((MM_BLOCK_SIZE + sizeof(WAVEHDR)) * MM_BLOCK_COUNT))) == NULL) { printf("Memory allocation error\n"); return -1; } mm_blocks = (WAVEHDR*)mm_buffer; mm_buffer += sizeof(WAVEHDR) * MM_BLOCK_COUNT; for(i = 0; i < MM_BLOCK_COUNT; i++) { mm_blocks[i].dwBufferLength = MM_BLOCK_SIZE; mm_blocks[i].lpData = mm_buffer; mm_buffer += MM_BLOCK_SIZE; } wfx.nSamplesPerSec = rate; wfx.wBitsPerSample = 16; wfx.nChannels = 2; wfx.cbSize = 0; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; if(waveOutOpen( &hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)mmOutProc, (DWORD_PTR)&mm_free_blocks, CALLBACK_FUNCTION ) != MMSYSERR_NOERROR) { printf("unable to open WAVE_MAPPER device\n"); return -1; } send_output = write_mm_output; close_output = close_mm_output; return 0;}int write_mm_output (char * output_data, int output_size) { WAVEHDR* current; int free_size = 0; int data_read = 0; current = &mm_blocks[mm_current_block]; while (output_size) { if(current->dwFlags & WHDR_PREPARED) waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); free_size = MM_BLOCK_SIZE - current->dwUser; if (free_size > output_size) free_size = output_size; memcpy(current->lpData + current->dwUser, &output_data[data_read], free_size); current->dwUser += free_size; output_size -= free_size; data_read += free_size; if (current->dwUser < MM_BLOCK_SIZE) { return 0; } current->dwBufferLength = MM_BLOCK_SIZE; waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); EnterCriticalSection(&waveCriticalSection); mm_free_blocks--;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -