home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
modiromppu
/
modiromppu.iso
/
PROGRAMS
/
ORGPACKS
/
DIDO4.ZIP
/
SOURCE.ZIP
/
DIDOREC.C
< prev
Wrap
C/C++ Source or Header
|
1995-01-17
|
8KB
|
266 lines
struct RIFF {
char rID[4];
DWORD rLen;
} riff;
struct FORMAT {
char fID[4];
DWORD fLen;
WORD wTag;
WORD wChannel;
DWORD nSample;
DWORD nByte;
WORD align;
WORD sample;
};
struct DATA {
char dID[4];
DWORD dLen;
};
struct WAVE {
char wID[4];
struct FORMAT fmt;
struct DATA data;
} wave;
char error[80]; // description of error, if any
int abortflag;
// Watch the cancel button
#pragma argsused
BOOL CALLBACK StatusDlgProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp)
{
if (msg==WM_INITDIALOG) {
SetDialogFont(hdlg,GetStockObject(ANSI_VAR_FONT));
CenterWindow(hdlg);
}
if (msg==WM_COMMAND && wp==IDCANCEL) abortflag=1;
return 0;
}
// Write out a block of sound data, do some processing if necessary.
// Return 0:failure, otherwise: bytes written.
WORD wavwrite(signed int *sample,WORD len,FILE *f)
{
if (hz44) {
if (stereo) { // 44khz stereo: no processing needed
if (fwrite(sample,len,1,f)==1) return len;
}
else { // 44khz mono: calculate left/right channel average, then write
WORD nsamples;
signed int *src=sample,*dst=sample;
nsamples=len>>2;
while (nsamples--) {
*dst=(WORD)(((DWORD)*src+*(src+1))>>1);
src+=2;
dst++;
}
if (fwrite(sample,len>>1,1,f)==1) return len>>1;
}
}
else {
if (stereo) { // 22khz stereo: condense samples (write only samples 0, 2, 4 etc)
WORD nsamples;
DWORD *src=(DWORD *)sample,*dst=(DWORD *)sample;
nsamples=len>>3;
while (nsamples--) {
*dst=*src; dst++; src+=2;
}
if (fwrite(sample,len>>1,1,f)==1) return len>>1;
}
else {
if (bit16) {// 22khz mono 16bits
WORD nsamples;
signed int *src=sample,*dst=sample;
nsamples=len>>3;
while (nsamples--) {
*dst=(WORD)(((DWORD)*src+*(src+1))>>1);
src+=4;
dst++;
}
if (fwrite(sample,len>>2,1,f)==1) return len>>2;
}
else { // 22 khz mono 8 bits
WORD nsamples;
signed int *src=sample;
signed char *dst=sample;
nsamples=len>>3;
while (nsamples--) {
*dst=128+HIBYTE((WORD)(((DWORD)*src+*(src+1))>>1));
src+=4;
dst++;
}
if (fwrite(sample,len>>3,1,f)==1) return len>>3;
}
}
}
return 0;
}
int record(char *image,DWORD startloc,DWORD size)
{
int first_time,i,bps;
WORD offset,synch_size,written;
DWORD end_pos,loc=startloc;
FILE *f;
HWND status;
MSG msg;
// Put up a modal dialog box (for status)
abortflag=0;
status=CreateDialog(hinst,"StatusDlg",0,StatusDlgProc);
if (!status) {
strcpy(error,"Cant create status window");
return 0;
}
strcpy(error,"");
// Create WAV file
f=fopen(image,"wb");
if (!f) {
strcpy(error,"cant create file");
return 0;
}
// Prepare RIFF+WAV header
bps=1; // bytes per sample - for a 8 bit mono sample
if (bit16) bps<<=1; // two times as much for 16 bit samples
if (stereo) bps<<=1; // another 2x as much for stereo
strcpy(riff.rID, "RIFF");
riff.rLen = FRAME_SIZE * (DWORD)size + sizeof(struct WAVE);
strcpy(wave.wID, "WAVE");
strcpy(wave.fmt.fID, "fmt ");
wave.fmt.fLen = sizeof(struct FORMAT) - 8;
wave.fmt.wTag = 1;
wave.fmt.wChannel = stereo?2:1; // nr of channels
wave.fmt.nSample = hz44?44100L:22050L; // sample rate
wave.fmt.nByte = (hz44?44100L:22050L) * bps; // avg dataspeed bytes/sec
wave.fmt.align = bps; // size of one sample, in bytes
wave.fmt.sample = bit16?16:8; // bits per sample
strcpy(wave.data.dID, "data");
wave.data.dLen = FRAME_SIZE * (DWORD)size;
if (fwrite(&riff,sizeof(struct RIFF),1,f)!=1) {
strcpy(error,"cant write to file (disk full?)");
goto Errorexit;
}
if (fwrite(&wave,sizeof(struct WAVE),1,f)!=1) {
strcpy(error,"cant write to file (disk full?)");
goto Errorexit;
}
// Read the data in blocks, first in memory
// loc: start position (sierra sector)
// size: number of sectors to read
// end_loc: sector number at where to end
wave.data.dLen = 0L;
first_time = 1;
end_pos = loc+size;
while (loc<end_pos) {
// Check abort
if (abortflag) {
strcpy(error," Recording cancelled ");
goto Errorexit;
}
// Update reading status
sprintf(s,"sector %ld / %ld",loc-startloc,size);
SetDlgItemText(status,STATUS,s);
// Read data in buffers
for (i=0;i<nbuf;i++) {
//TODO: Fix bugs with the last sector(s)
/*res=*/ ReadLong(loc,NBLOCK,bufseg[i]);
loc+=NBLOCK;
}
/*
if (res!=0x0100) {
sprintf(error,"cant read raw sector, status %04x",res);
goto Errorexit;
}
*/
// Except for first recording, synchronize data to previous data
if (first_time == 0) {
offset = 0;
synch_size = SYNCH_SIZE;
while (offset == 0) {
for (i=(NBLOCK/4)*FRAME_SIZE;i<(((WORD)NBLOCK*FRAME_SIZE)-synch_size);i+=4) {
if (memcmp(pprev_end+(NBLOCK/2)*FRAME_SIZE,pbuf[0]+i,synch_size) == 0) {
if (offset==0)
offset=i;
else {
synch_size *= 2;
if (synch_size>4096) {
strcpy(error,"Synchronisation failed. Retry the operation. Close some other programs, if possible.");
goto Errorexit;
}
offset=0;
break;
}
}
}
if (offset==0) {
strcpy(error,"Synchronisation failed, no matching block. Retry the operation. Close some other programs, if possible.");
goto Errorexit;
}
}
}
else
offset = 0;
first_time=0;
memcpy(pprev_end,pbuf[nbuf-1],(WORD)((DWORD)FRAME_SIZE*NBLOCK));
// Write all buffers to disk, except the last buffer
for (i=0;i<nbuf-1;i++) {
written=wavwrite((signed int *)(pbuf[i]+offset),((DWORD)FRAME_SIZE*NBLOCK)-offset,f);
if (!written) {
strcpy(error,"cant write to file (disk full?)");
goto Errorexit;
}
wave.data.dLen+=written;
offset=0;
}
sprintf(s,"%s %ld Kbytes",Sector2MSF(loc-startloc),wave.data.dLen/1024);
SetDlgItemText(status,STATUSDISK,s);
// Write only half of last buffer, The next loop, after synchronisation the rest will be written
written=wavwrite((signed int *)pbuf[nbuf-1],(DWORD)FRAME_SIZE*(NBLOCK/2),f);
if (!written) {
strcpy(error,"cant write to file (disk full?)");
goto Errorexit;
}
wave.data.dLen+=written;
loc-=NBLOCK;
// Give some time slices
while (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// Fix WAV header
fseek(f,0L,SEEK_SET);
riff.rLen = wave.data.dLen + sizeof(struct WAVE);
if (fwrite(&riff,sizeof(struct RIFF),1,f)!=1) {
strcpy(error,"cant write to file (disk full?)");
goto Errorexit;
}
if (fwrite(&wave,sizeof(struct WAVE),1,f)!=1) {
strcpy(error,"cant write to file (disk full?)");
goto Errorexit;
}
fclose(f);
DestroyWindow(status);
return 1;
Errorexit:
if (f) fclose(f);
unlink(image);
DestroyWindow(status);
return 0;
}