pcm 스트림을 wav 파일로 만들기
글쓴이: 송지석 / 작성시간: 월, 2003/06/23 - 10:05오전
안녕하세요
요새 adpcm 쪽을 보고 있는데요..
인터넷에서 adpcm 코덱을 찾았는데요.
제대로 된 것인 지를 알아보려면 디코딩 한 것을 플레이를 해봐야 되잖아요?
쉽게 생각하면 이 PCM 데이터를 WAV 파일 형식에 맞게 묶어서 만들면 일반 음악 재생 프로그램에서 플레이될텐데요.. 이걸 RIFF/WAv 포맷 스터디 하고 프로그램 짜서 디버깅 하려니 좀 시간이 오래 걸릴 것 같아서 말입니다.
어딘가 유틸리티가 있을 것 같은데요.. PCM raw 데이터를 WAV파일 포맷에 맞게 만들어주는 것이요.
아니면 PCM 자체를 플레이 할 수 있거나요.
일단 cat my.pcm > /dev/sound0 를 해보니 음악을 엄청 빨리 돌리는 것 처럼 들리더군요. 어찌 해야 할 지.. 음..
혹시 방법을 알고 계신 분 답변 부탁드립니다.
Forums:


간단하게 지금 예제 한번 만들어 봤습니다.WAVE의 형식 모두를 지원
간단하게 지금 예제 한번 만들어 봤습니다.
WAVE의 형식 모두를 지원하지는 못하겠네요. 다 구현하려면
오래걸려서.....
대충 소스보시고 형식을 이해하기만 하면 쉽게 하실듯.
/* Copyright (c) 2002 Information Equipment co.,LTD. All Right Reserved. Code by JaeHyuk Cho <minzkn@infoeq.co.kr> - Little endian base - Simple is best */ #if !defined(DEF_wave_c) #define DEF_wave_c "wave.c" #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/ioctl.h> #include <fcntl.h> #include <string.h> #include <linux/soundcard.h> /* Little endian */ #define DEF_WAVE_MAGIC(a,b,c,d) ( (a) | (b << 8) | (c << 16) | (d << 24) ) typedef struct { unsigned long Magic; /* "RIFF" */ unsigned long Length; /* File length */ unsigned long Type; /* "WAVE" */ }t_WAVE_Header; typedef struct { unsigned short Format; unsigned short Channels; /* 1 = Mono, 2 = Stereo */ unsigned long Frequency; /* Frequency of sample */ unsigned long BytesPerSecond; /* Bytes per second */ unsigned short BytesPerSample; /* Bytes per sample */ unsigned short BitsPerSample; /* Bits per sample */ }t_WAVE_FMT; typedef struct { unsigned long Magic; /* "data" */ unsigned long Length; /* Sample count */ }t_WAVE_Chunk; int main(int s_Argc, char **s_Argv); int MZ_WAVE_Play(int s_Handle); int main(int s_Argc, char **s_Argv) { fprintf(stdout, "MZWAVE Release 0.0.1 - Copyright (c) Information Equipment co.,LTD. - %s %s\n", __DATE__, __TIME__); fprintf(stdout, "Code by JaeHyuk Cho , ApplicationName: MZ PCM player , Made in korea.\n\n"); if(s_Argc > 1) { int s_Handle; s_Handle = open(s_Argv[1], O_RDONLY); if(s_Handle >= 0) { MZ_WAVE_Play(s_Handle); close(s_Handle); } else fprintf(stderr, "Can not open \"%s\"\n", s_Argv[1]); } else fprintf(stderr, "Usage: %s <wave file>\n", s_Argv[0]); fprintf(stdout, "\nEnd of %s\n", s_Argv[0]); return(0); } int MZ_WAVE_Play(int s_Handle) { int s_Return = (-1); int s_ReadSize, s_DSP, s_DSP_Format, s_DSP_Channels; t_WAVE_Header s_WAVE_Header; t_WAVE_FMT s_WAVE_FMT; t_WAVE_Chunk s_WAVE_Chunk; s_ReadSize = read(s_Handle, (void *)&s_WAVE_Header, sizeof(s_WAVE_Header)); if(s_ReadSize == sizeof(s_WAVE_Header)) { if(s_WAVE_Header.Magic == DEF_WAVE_MAGIC('R', 'I', 'F', 'F')) { fprintf(stdout, "INFO: File length = %lu\n", s_WAVE_Header.Length); switch(s_WAVE_Header.Type) { case DEF_WAVE_MAGIC('W', 'A', 'V', 'E'): s_ReadSize = read(s_Handle, (void *)&s_WAVE_Chunk, sizeof(s_WAVE_Chunk)); if(s_ReadSize == sizeof(s_WAVE_Chunk)) { if(s_WAVE_Chunk.Magic == DEF_WAVE_MAGIC('f', 'm', 't', ' ')) { fprintf(stdout, "INFO: Chunk length = %lu\n", s_WAVE_Chunk.Length); s_ReadSize = read(s_Handle, (void *)&s_WAVE_FMT, sizeof(s_WAVE_FMT)); if(s_ReadSize == sizeof(s_WAVE_FMT)) { fprintf(stdout, "INFO: Format = 0x%04x\n" , (unsigned int )s_WAVE_FMT.Format); fprintf(stdout, "INFO: Channels = %u\n" , (unsigned int )s_WAVE_FMT.Channels); fprintf(stdout, "INFO: Frequency = %lu\n" , (unsigned long)s_WAVE_FMT.Frequency); fprintf(stdout, "INFO: Bytes per second = %lu\n" , (unsigned long)s_WAVE_FMT.BytesPerSecond); fprintf(stdout, "INFO: Bytes per sample = %u\n" , (unsigned int )s_WAVE_FMT.BytesPerSample); fprintf(stdout, "INFO: Bits per sample = %u\n" , (unsigned int )s_WAVE_FMT.BitsPerSample); s_DSP = open("/dev/dsp", O_WRONLY); if(s_DSP < 0)s_DSP = open("/dev/audio", O_WRONLY); if(s_DSP >= 0) { if(s_WAVE_FMT.BytesPerSample == 1)s_DSP_Format = AFMT_S8; else s_DSP_Format = AFMT_S16_LE; s_DSP_Channels = s_WAVE_FMT.Channels; if(ioctl(s_DSP, SNDCTL_DSP_SETFMT, &s_DSP_Format) == 0) { if(ioctl(s_DSP, SNDCTL_DSP_CHANNELS, &s_DSP_Channels) == 0) { if(ioctl(s_DSP, SNDCTL_DSP_SPEED, &s_WAVE_FMT.Frequency) == 0) { unsigned char s_Buffer[32 << 10]; s_Return = 0; do { s_ReadSize = read(s_Handle, (void *)&s_Buffer[0], sizeof(s_Buffer)); if(s_ReadSize > 0) { s_Return += s_ReadSize; write(s_DSP, (void *)&s_Buffer[0], s_ReadSize); } }while(s_ReadSize > 0); } else fprintf(stderr, "Can not ioctl SNDCTL_DSP_SPEED !!!\n"); } else fprintf(stderr, "Can not ioctl SNDCTL_DSP_CHANNELS !!!\n"); } else fprintf(stderr, "Can not ioctl SNDCTL_DSP_SETFMT !!!\n"); close(s_DSP); } else fprintf(stderr, "Can not open DSP !!!\n"); } else fprintf(stderr, "Can not read s_WAVE_FMT !!!\n"); } else fprintf(stderr, "Invalid Magic #1\n"); } else fprintf(stderr, "Can not read s_WAVE_Chunk !!!\n"); break; default: fprintf(stderr, "Not support format !!!\n"); break; } } else fprintf(stderr, "Invalid Magic #0 !!!\n"); } else fprintf(stderr, "Can not read s_WAVE_Header !!!\n"); return(s_Return); } #endif /* End of source */이런 것이 있네요. perl 모듈이니 사용에 간편할 것 같습니다.
이런 것이 있네요. perl 모듈이니 사용에 간편할 것 같습니다.
http://search.cpan.org/author/FOOF/libao-perl_0.03-1/pcmplay
War doesnt determine whos right, just whos left.
SOX - sox.sf.net
SOX(Sound of Exchange) 라는 프로그램이 있습니다.
sox.sf.net에서 다운받으실 수 있습니다.
다양한 사운드 포맷간의 변환을 지원합니다.
pcm을 .wav(RIFF)로 변환하시려면 다음과 같이 해보세요.
sox -t raw -r <sampling rate> <pcm file name> <wav filename>제가 몇 번 해 본적이 있는데 잘 동작합니다.
(다만 pcm파일을 sampling rate를 정확히 모르신다면
속도가 굉장히 빨리 들릴 겁니다. 느리게 들리거나 ^^)
<wav filename>에는 꼭 확장자를 ".wav"로 적어 주세요.
감사합니다. SoX를 사용해서 raw 데이터를 wav로 변환해 들을 수
감사합니다. SoX를 사용해서 raw 데이터를 wav로 변환해 들을 수 있었습니다.
rommance.net
댓글 달기