📄 file.c
字号:
*/ return wfile;}/* * Open /dev/dsp for reading or writing: */DSPFILE *OpenDSP(WAVFILE *wfile,int omode,ErrFunc erf) { int e; /* Saved errno value */ int t; /* Work int */ unsigned long ul; /* Work unsigned long */ DSPFILE *dfile = (DSPFILE *) malloc(sizeof (DSPFILE)); v_erf = erf; /* Set error reporting function */ if ( dfile == NULL ) { err("%s: Opening DSP device",sys_errlist[errno=ENOMEM]); return NULL; } memset(dfile,0,sizeof *dfile); dfile->dspbuf = NULL; /* * Open the device driver: */ if ( (dfile->fd = open(env_AUDIODEV,omode,0)) < 0 ) { err("%s:\nOpening audio device %s", sys_errlist[errno], env_AUDIODEV); goto errxit; } /* * Determine the audio device's block size. Should be done after * setting sampling rate etc. */ if ( ioctl(dfile->fd,SNDCTL_DSP_GETBLKSIZE,&dfile->dspblksiz) < 0 ) { err("%s: Optaining DSP's block size",sys_errlist[errno]); goto errxit; } /* * Check the range on the buffer sizes: */ /* Minimum was 4096 but es1370 returns 1024 for 44.1kHz, 16 bit */ /* and 64 for 8130Hz, 8 bit */ if ( dfile->dspblksiz < 32 || dfile->dspblksiz > 65536 ) { err("%s: Audio block size (%d bytes)", sys_errlist[errno=EINVAL], (int)dfile->dspblksiz); goto errxit; } /* * Allocate a buffer to do the I/O through: */ if ( (dfile->dspbuf = (char *) malloc(dfile->dspblksiz)) == NULL ) { err("%s: For DSP I/O buffer",sys_errlist[errno]); goto errxit; } /* * Set the data bit size: */ t = wfile->wavinfo.DataBits; if ( ioctl(dfile->fd,SNDCTL_DSP_SAMPLESIZE,&t) < 0 ) { err("%s: Setting DSP to %u bits",sys_errlist[errno],(unsigned)t); goto errxit; } /* * Set the mode to be Stereo or Mono: */ t = wfile->wavinfo.Channels == Stereo ? 1 : 0; if ( ioctl(dfile->fd,SNDCTL_DSP_STEREO,&t) < 0 ) { err("%s: Unable to set DSP to %s mode", sys_errlist[errno], t?"Stereo":"Mono"); goto errxit; } printf("Stereo Mode is %d!\n",t); /* * Set the sampling rate: */ ul = wfile->wavinfo.SamplingRate; if ( ioctl(dfile->fd,SNDCTL_DSP_SPEED,&ul) < 0 ) { err("Unable to set audio sampling rate",sys_errlist[errno]); goto errxit; } printf("Sampling rate is %ld!\n",ul); /* * Return successfully opened device: */ return dfile; /* Return file descriptor */ /* * Failed to open/initialize properly: */errxit: e = errno; /* Save the errno value */ if ( dfile->fd >= 0 ) close(dfile->fd); /* Close device */ if ( dfile->dspbuf != NULL ) free(dfile->dspbuf); free(dfile); errno = e; /* Restore error code */ return NULL; /* Return error indication */}/* * Close the DSP device: */intCloseDSP(DSPFILE *dfile,ErrFunc erf) { int fd; v_erf = erf; /* Set error reporting function */ if ( dfile == NULL ) { err("%s: DSPFILE is not open",sys_errlist[errno=EINVAL]); return -1; } fd = dfile->fd; if ( dfile->dspbuf != NULL ) free(dfile->dspbuf); free(dfile); if ( close(fd) ) { err("%s: Closing DSP fd %d",sys_errlist[errno],fd); return -1; } return 0;}/* * Play DSP from WAV file: */intPlayDSP(DSPFILE *dfile,WAVFILE *wfile,DSPPROC work_proc,ErrFunc erf) { UInt32 byte_count = (UInt32) wfile->wavinfo.Samples; int bytes; int n; int byte_modulo; int total_bytes, update_bytes; SVRMSG msg; v_erf = erf; /* Set error reporting function */ /* * Check that the WAVFILE is open for reading: */ if ( wfile->rw != 'R' ) { err("%s: WAVFILE must be open for reading",sys_errlist[errno=EINVAL]); return -1; } /* * First determine how many bytes are required for each channel's sample: */ switch ( wfile->wavinfo.DataBits ) { case 8 : byte_count = 1; break; case 16 : byte_count = 2; break; default : err("%s: Cannot process %u bit samples", sys_errlist[errno=EINVAL], (unsigned)wfile->wavinfo.DataBits); return -1; } /* * Allow for Mono/Stereo difference: */ if ( wfile->wavinfo.Channels == Stereo ) byte_count *= 2; /* Twice as many bytes for stereo */ else if ( wfile->wavinfo.Channels != Mono ) { err("%s: DSPFILE control block is corrupted (chan_mode)", sys_errlist[errno=EINVAL]); return -1; } byte_modulo = byte_count; /* This many bytes per sample */ byte_count = wfile->wavinfo.Samples * byte_modulo; /* Total bytes to process */ total_bytes = byte_count; /* Number of bytes to write between client updates. Must be */ /* a multiple of dspblksiz. */ update_bytes = ((wfile->wavinfo.SamplingRate*byte_modulo) / (RECPLAY_UPDATES_PER_SEC*dfile->dspblksiz)) * dfile->dspblksiz; if ( ioctl(dfile->fd,SNDCTL_DSP_SYNC,0) != 0 ) err("%s: ioctl(%d,SNDCTL_DSP_SYNC,0)",sys_errlist[errno]); /* Seek to requested start sample */ lseek(wfile->fd,wfile->StartSample*byte_modulo,SEEK_CUR); for ( ; byte_count > 0 && wfile->wavinfo.DataBytes > 0; byte_count -= (UInt32) n ) { bytes = (int) ( byte_count > dfile->dspblksiz ? dfile->dspblksiz : byte_count ); if ( bytes > wfile->wavinfo.DataBytes ) /* Size bigger than data chunk? */ bytes = wfile->wavinfo.DataBytes; /* Data chunk only has this much left */ if ( (n = read(wfile->fd,dfile->dspbuf,bytes)) != bytes ) { if ( n >= 0 ) err("Unexpected EOF reading samples from WAV file",sys_errlist[errno=EIO]); else err("Reading samples from WAV file",sys_errlist[errno]); goto errxit; } if ((clntIPC >= 0) && !((total_bytes-byte_count) % update_bytes)) { msg.msg_type = ToClnt_PlayState; msg.bytes = sizeof(msg.u.toclnt_playstate); msg.u.toclnt_playstate.SamplesLeft = byte_count / byte_modulo; msg.u.toclnt_playstate.CurrentSample = wfile->num_samples - msg.u.toclnt_playstate.SamplesLeft; MsgToClient(clntIPC,&msg,0); /* Tell client playback status */ } if ( write(dfile->fd,dfile->dspbuf,n) != n ) { err("Writing samples to audio device",sys_errlist[errno]); goto errxit; } wfile->wavinfo.DataBytes -= (UInt32) bytes; /* We have fewer bytes left to read */ /* * The work procedure function is called when operating * in server mode to check for more server messages: */ if ( work_proc != NULL && work_proc(dfile) ) /* Did work_proc() return TRUE? */ break; /* Yes, quit playing */ } #if 0 /* I think this is doing a destructive flush: disabled */ if ( ioctl(dfile->fd,SNDCTL_DSP_SYNC,0) != 0 ) err("%s: ioctl(%d,SNDCTL_DSP_SYNC,0)",sys_errlist[errno]);#endif /* Update client time display at end of sucessful play */ if (clntIPC >= 0) { msg.msg_type = ToClnt_PlayState; msg.bytes = sizeof(msg.u.toclnt_playstate); msg.u.toclnt_playstate.SamplesLeft = byte_count / byte_modulo; msg.u.toclnt_playstate.CurrentSample = wfile->num_samples - msg.u.toclnt_playstate.SamplesLeft; MsgToClient(clntIPC,&msg,0); /* Tell client playback status */ } return 0; /* All samples played successfully */errxit: return -1; /* Indicate error return */}/* * Record DSP to WAV file: If samples == 0UL, then record continues until * a bRecordStopPosted becomes true (via SIGINT). */intRecordDSP(DSPFILE *dfile,WAVFILE *wfile,UInt32 samples,DSPPROC work_proc,ErrFunc erf) { UInt32 byte_count = (UInt32) wfile->wavinfo.Samples; UInt32 chunk; int bytes; int n; UInt32 bytes_per_sample = 0; UInt32 bytes_written = 0; char *mybuf; char *dspbuf_t; char *dspbuf_p; int i; int update_bytes; SVRMSG msg; v_erf = erf; /* Set error reporting function */// char *mybuf;// char *dspbuf_t;// int i; /* * Check that the WAVFILE is open for writing: */ if ( wfile->rw != 'W' ) { err("WAVFILE must be open for writing",sys_errlist[errno=EINVAL]); return -1; } /* * First determine how many bytes are required for each channel's sample: */ switch ( wfile->wavinfo.DataBits ) { case 8 : byte_count = 1; break; case 12 : case 16 : byte_count = 2; break; default : err("Cannot process %u bit samples", sys_errlist[errno=EINVAL], (unsigned)wfile->wavinfo.DataBits); return -1; } /* * Allow for Mono/Stereo difference: */ if ( wfile->wavinfo.Channels == Stereo ) byte_count *= 2; /* Twice as many bytes for stereo */ else if ( wfile->wavinfo.Channels != Mono ) { err("DSPFILE control block is corrupted (chan_mode)",sys_errlist[errno=EINVAL]); return -1; } bytes_per_sample = byte_count; /* Save for close later */ if ( samples > 0 ) byte_count *= wfile->wavinfo.Samples; /* Total number of bytes to collect */ else { /* Compute a smallish sized chunk of the correct modulo bytes */ chunk = dfile->dspblksiz > 4096 ? 4096 : dfile->dspblksiz; byte_count = (chunk + (byte_count-1)) & ~(byte_count-1); } /* Number of bytes to write between client updates. Must be */ /* a multiple of dspblksiz. */ update_bytes = ((wfile->wavinfo.SamplingRate*bytes_per_sample)/ (RECPLAY_UPDATES_PER_SEC*dfile->dspblksiz))*dfile->dspblksiz; mybuf=malloc(dfile->dspblksiz>>1); memset(mybuf,0,(dfile->dspblksiz>>1)); while ( 1 ) { /* * Determine how many samples to read: */ if ( samples > 0 ) bytes = byte_count > dfile->dspblksiz ? dfile->dspblksiz : byte_count; else bytes = byte_count; /* Record until interrupted */ /* * Read a block of samples: */ if ( (n = read(dfile->fd,dfile->dspbuf,bytes)) < 0 ) { err("Reading DSP device",sys_errlist[errno]); goto errxit; } else if ( n == 0 ) break; dspbuf_t=mybuf; dspbuf_p=dfile->dspbuf; for(i=0;i<n/4;i++) { *mybuf++=*dfile->dspbuf++; *mybuf++=*dfile->dspbuf++; dfile->dspbuf+=2; } if(n%4!=0) { *mybuf++=*dfile->dspbuf++; *mybuf++=*dfile->dspbuf++; n=(n>>1)+1; } else n=n>>1; /* * Write a block of samples to the file: */ if ( (bytes = write(wfile->fd,dspbuf_t,n)) < 0 ) { err("Writing WAV samples to %s",sys_errlist[errno],wfile->Pathname); goto errxit; } else if ( bytes != n ) { if ( bytes > 0 ) bytes_written += bytes; err("Did not write all WAV successfully",sys_errlist[errno=EIO]); goto errxit; } mybuf=dspbuf_t; dfile->dspbuf=dspbuf_p; bytes_written += bytes; if ((clntIPC >= 0) && !(bytes_written % update_bytes)) { msg.msg_type = ToClnt_RecState; msg.bytes = sizeof(msg.u.toclnt_recstate); msg.u.toclnt_recstate.bytes_written = bytes_written; msg.u.toclnt_recstate.num_samples = bytes_written / bytes_per_sample; MsgToClient(clntIPC,&msg,0); /* Tell client playback status */ } if ( samples > 0 ) if ( (byte_count -= (unsigned) n) < 1 ) break; /* * The work procedure function is called when operating * in server mode to check for more server messages: */ if ( work_proc != NULL && work_proc(dfile) ) /* Did work_proc() return TRUE? */ break; /* Yes, quit recording */ } wfile->wavinfo.Samples = bytes_written & ~(bytes_per_sample-1); return 0; /* All samples played successfully */errxit: wfile->wavinfo.Samples = bytes_written & ~(bytes_per_sample-1); return -1; /* Indicate error return */}/* $Source: /home/cvs/wavplay/file.c,v $ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -