/* * Copyright (C) 2010,2019 Klaus Michael Indlekofer. All rights reserved. * * m.indlekofer@gmx.de * * 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. */ #include "commoninclude.h" #include "akaiutil_wav.h" int wav_write_head(int outdes, u_int datasize,u_int chnr,u_int samprate,u_int bitnr, u_int extrasize) { struct wav_riffhead_s wavriffhead; struct wav_chunkhead_s wavchunkhead; struct wav_fmthead_s wavfmthead; u_int drate; /* create WAVE RIFF header */ bzero(&wavriffhead,sizeof(struct wav_riffhead_s)); bcopy(WAV_RIFFHEAD_RIFFSTR,wavriffhead.riffstr,4); { u_int fsize; fsize=WAV_HEAD_SIZE-sizeof(struct wav_chunkhead_s)+datasize+extrasize; wavriffhead.fsize[0]=0xff&fsize; wavriffhead.fsize[1]=0xff&(fsize>>8); wavriffhead.fsize[2]=0xff&(fsize>>16); wavriffhead.fsize[3]=0xff&(fsize>>24); } bcopy(WAV_RIFFHEAD_WAVESTR,wavriffhead.wavestr,4); /* write WAVE RIFF header */ if (WRITE(outdes,&wavriffhead,sizeof(struct wav_riffhead_s))!=sizeof(struct wav_riffhead_s)){ PRINTF_ERR("cannot write WAVE RIFF header\n"); return -1; } /* create FMT chunk header */ bcopy(WAV_CHUNKHEAD_FMTSTR,wavchunkhead.typestr,4); { u_int csize; csize=sizeof(struct wav_fmthead_s); wavchunkhead.csize[0]=0xff&csize; wavchunkhead.csize[1]=0xff&(csize>>8); wavchunkhead.csize[2]=0xff&(csize>>16); wavchunkhead.csize[3]=0xff&(csize>>24); } /* write chunk header */ if (WRITE(outdes,&wavchunkhead,sizeof(struct wav_chunkhead_s))!=sizeof(struct wav_chunkhead_s)){ PRINTF_ERR("cannot write WAVE FMT header\n"); return -1; } /* set FMT header */ wavfmthead.ftag[0]=0xff&WAV_HEAD_FTAG_PCM; wavfmthead.ftag[1]=0xff&(WAV_HEAD_FTAG_PCM>>8); wavfmthead.chnr[0]=0xff&chnr; wavfmthead.chnr[1]=0xff&(chnr>>8); wavfmthead.srate[0]=0xff&samprate; wavfmthead.srate[1]=0xff&(samprate>>8); wavfmthead.srate[2]=0xff&(samprate>>16); wavfmthead.srate[3]=0xff&(samprate>>24); drate=chnr*samprate*(bitnr/8); /* chnr!!! */ wavfmthead.drate[0]=0xff&drate; wavfmthead.drate[1]=0xff&(drate>>8); wavfmthead.drate[2]=0xff&(drate>>16); wavfmthead.drate[3]=0xff&(drate>>24); wavfmthead.balign[0]=0xff&((bitnr/8)*chnr); /* chnr!!! */ wavfmthead.balign[1]=0xff&(((bitnr/8)*chnr)>>8); /* chnr!!! */ wavfmthead.bitnr[0]=0xff&bitnr; wavfmthead.bitnr[1]=0xff&(bitnr>>8); /* write WAVE FMT header */ if (WRITE(outdes,&wavfmthead,sizeof(struct wav_fmthead_s))!=sizeof(struct wav_fmthead_s)){ PRINTF_ERR("cannot write WAVE FMT header\n"); return -1; } /* create WAVE DATA chunk header */ bcopy(WAV_CHUNKHEAD_DATASTR,wavchunkhead.typestr,4); wavchunkhead.csize[0]=0xff&datasize; wavchunkhead.csize[1]=0xff&(datasize>>8); wavchunkhead.csize[2]=0xff&(datasize>>16); wavchunkhead.csize[3]=0xff&(datasize>>24); /* write chunk header */ if (WRITE(outdes,&wavchunkhead,sizeof(struct wav_chunkhead_s))!=sizeof(struct wav_chunkhead_s)){ PRINTF_ERR("cannot write WAVE DATA header\n"); return -1; } return 0; } int wav_read_head(int indes, u_int *bcountp, u_int *datasizep,u_int *chnrp,u_int *sampratep,u_int *bitnrp, u_int *extrasizep, char **errstrp) { struct wav_riffhead_s wavriffhead; struct wav_chunkhead_s wavchunkhead; struct wav_fmthead_s wavfmthead; u_int i; u_int bcount; u_int remain; u_int csize; u_int chnr; u_int samprate; u_int bitnr; bcount=0; /* no bytes read yet */ /* read WAVE RIFF header */ if (READ(indes,(char *)&wavriffhead,sizeof(struct wav_riffhead_s))!=sizeof(struct wav_riffhead_s)){ if (errstrp!=NULL){ *errstrp="read WAVE RIFF header"; } return -1; } bcount+=sizeof(struct wav_riffhead_s); /* check riffstr */ for (i=0;i<4;i++){ if (WAV_RIFFHEAD_RIFFSTR[i]!=wavriffhead.riffstr[i]){ if (errstrp!=NULL){ *errstrp="no RIFF"; } return -1; } } /* determine remaining file size */ remain=wavriffhead.fsize[0] +(wavriffhead.fsize[1]<<8) +(wavriffhead.fsize[2]<<16) +(wavriffhead.fsize[3]<<24); if (remain>8)))){ if (errstrp!=NULL){ *errstrp="invalid ftag, must be PCM format"; } return -1; } /* get chnr */ chnr=wavfmthead.chnr[0] +(wavfmthead.chnr[1]<<8); if (chnr==0){ if (errstrp!=NULL){ *errstrp="invalid chnr"; } return -1; } /* set samprate */ samprate=wavfmthead.srate[0] +(wavfmthead.srate[1]<<8) +(wavfmthead.srate[2]<<16) +(wavfmthead.srate[3]<<24); /* XXX check drate: must be chnr*samprate*(bitnr/8) */ /* get bitnr */ bitnr=wavfmthead.bitnr[0] +(wavfmthead.bitnr[1]<<8); if (bitnr==0){ if (errstrp!=NULL){ *errstrp="invalid bitnr"; } return -1; } /* XXX check balign: must be (bitnr/8)*chnr */ /* search for data chunk */ for (;;){ /* read next chunk */ if (remain