Make WAV file reading correct so that optional chunks can be tolerated

The WAV file format allows for optional header content, allow for this
in preparation for adding some metadata to WSJT-X recorded WAV files.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6335 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2016-01-02 14:29:02 +00:00
parent 0cf18c445f
commit 26e5ea963e
5 changed files with 99 additions and 23 deletions

View File

@ -368,6 +368,7 @@ set (wsjt_FSRCS
lib/polyfit.f90
lib/prog_args.f90
lib/ps4.f90
lib/readwav.f90
lib/rectify_msk.f90
lib/savec2.f90
lib/sec_midn.f90

View File

@ -1,6 +1,8 @@
#include "getfile.h"
#include <QDir>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#ifdef WIN32
@ -60,10 +62,41 @@ void getfile(QString fname, int ntrperiod)
memset(dec_data.d2,0,2*npts);
if(fp != NULL) {
struct
{
char id[4];
uint32_t size;
} desc;
char type[4];
struct
{
uint16_t nfmt2;
uint16_t nchan2;
uint32_t nsamrate;
uint32_t nbytesec;
uint16_t nbytesam2;
uint16_t nbitsam2;
} fmt;
// read header
fread(&desc, 1, sizeof desc, fp); // RIFF
fread(type, 1, sizeof type, fp); // WAVE
do
{
fread(&desc, 1, sizeof desc, fp); // WAVE component
if (!memcmp(desc.id,"fmt ",4)) {
fpos_t pos;
fgetpos(fp,&pos);
fread(&fmt,1,sizeof fmt,fp);
fsetpos(fp,&pos);
}
if (!memcmp(desc.id,"data",sizeof desc.id)) break;
} while (!fseek(fp,(desc.size + 1) / 2 * 2,SEEK_CUR));
// Read (and ignore) a 44-byte WAV header; then read data
int n=fread(&hdr,1,44,fp);
n=fread(dec_data.d2,2,npts,fp);
if(hdr.nsamrate==11025) wav12_(dec_data.d2,dec_data.d2,&n,&hdr.nbitsam2);
// int n=fread(&hdr,1,44,fp);
int n=fread(dec_data.d2,2,npts,fp);
if(hdr.nsamrate==11025) wav12_(dec_data.d2,dec_data.d2,&n,(short*)&fmt.nbitsam2);
fclose(fp);
dec_data.params.newdat=1;
dec_data.params.kin=n;

View File

@ -6,17 +6,17 @@ program jt65
use timer_module, only: timer
use timer_impl, only: init_timer
use jt65_test
use readwav
character c
logical :: display_help=.false.,nrobust=.false.
integer*4 ihdr(11)
type(wav_header) :: wav
integer*2 id2(NZMAX)
real*4 dd(NZMAX)
character*80 infile
character(len=500) optarg
character*12 mycall,hiscall
character*6 hisgrid
equivalence (lenfile,ihdr(2))
type (option) :: long_options(10) = [ &
option ('aggressive',.true.,'a','aggressiveness [0-10], default AGGR=0','AGGR'), &
option ('freq',.true.,'f','signal frequency, default FREQ=1270','FREQ'), &
@ -95,21 +95,17 @@ program jt65
minsync=0
call get_command_argument(ifile,optarg,narglen)
infile=optarg(:narglen)
open(10,file=infile,access='stream',status='old',err=998)
call timer('read ',0)
read(10) ihdr
call wav%read (infile)
i1=index(infile,'.wav')
if( i1 .eq. 0 ) i1=index(infile,'.WAV')
read(infile(i1-4:i1-1),*,err=998) nutc
npts=52*12000
read(10) id2(1:npts)
read(unit=wav%lun) id2(1:npts)
close(unit=wav%lun)
call timer('read ',1)
dd(1:npts)=id2(1:npts)
dd(npts+1:)=0.
! open(56,file='subtracted.wav',access='stream',status='unknown')
! write(56) ihdr(1:11)
call test(dd,nutc,nfa,nfb,nfqso,ntol,nsubmode, &
n2pass,nrobust,ntrials,naggressive, &
mycall,hiscall,hisgrid,nexp_decoded)

View File

@ -9,11 +9,12 @@ program jt9
use FFTW3
use timer_module, only: timer
use timer_impl, only: init_timer, fini_timer
use readwav
include 'jt9com.f90'
integer(C_INT) iret
integer*4 ihdr(11)
type(wav_header) wav
real*4 s(NSMAX)
character c
character(len=500) optarg, infile
@ -172,10 +173,8 @@ program jt9
do iarg = offset + 1, offset + remain
call get_command_argument (iarg, optarg, arglen)
infile = optarg(:arglen)
open(10,file=infile,access='stream',status='old',err=998)
read(10) ihdr
nfsample=ihdr(7)
nutc=ihdr(1) !Silence compiler warning
call wav%read (infile)
nfsample=wav%audio_format%sample_rate
i1=index(infile,'.wav')
if(i1.lt.1) i1=index(infile,'.WAV')
if(infile(i1-5:i1-5).eq.'_') then
@ -218,7 +217,7 @@ program jt9
do iblk=1,npts/kstep
k=iblk*kstep
call timer('read_wav',0)
read(10,end=3) shared_data%id2(k-kstep+1:k)
read(unit=wav%lun,end=3) shared_data%id2(k-kstep+1:k)
go to 4
3 call timer('read_wav',1)
print*,'EOF on input file ',infile
@ -239,7 +238,7 @@ program jt9
if(nhsym.ge.181) exit
endif
enddo
close(10)
close(unit=wav%lun)
shared_data%params%nutc=nutc
shared_data%params%ndiskdat=.true.
shared_data%params%ntr=60
@ -290,10 +289,6 @@ program jt9
call timer('jt9 ',1)
call timer('jt9 ',101)
go to 999
998 print*,'Cannot open file:'
print*,infile
999 continue
! Output decoder statistics

51
lib/readwav.f90 Normal file
View File

@ -0,0 +1,51 @@
module readwav
implicit none
type format_chunk
integer*2 audio_format
integer*2 num_channels
integer sample_rate
integer byte_rate
integer*2 block_align
integer*2 bits_per_sample
end type format_chunk
type, public :: wav_header
integer :: lun
type(format_chunk) :: audio_format
contains
procedure :: read
end type wav_header
private
contains
subroutine read (this, filename)
implicit none
type riff_descriptor
character(len=4) :: id
integer :: size
end type riff_descriptor
class(wav_header), intent(inout) :: this
character(len=*), intent(in) :: filename
integer :: filepos
type(riff_descriptor) :: desc
character(len=4) :: riff_type
open (newunit=this%lun, file=filename, access='stream', form='unformatted', status='old')
read (unit=this%lun) desc,riff_type
inquire (unit=this%lun, pos=filepos)
do
read (unit=this%lun, pos=filepos) desc
inquire (unit=this%lun, pos=filepos)
if (desc%id .eq. 'fmt ') then
read (unit=this%lun) this%audio_format
else if (desc%id .eq. 'data') then
exit
end if
filepos = filepos + (desc%size + 1) / 2 * 2 ! pad to even alignment
end do
end subroutine read
end module readwav