Пример #1
0
 int SNDWAV_PrepareWAVParams(WAVContainer_t *wav) 
 { 
     assert(wav); 
  	//硬件参数赋值
     uint16_t channels = DEFAULT_CHANNELS; 
     uint16_t sample_rate = DEFAULT_SAMPLE_RATE; 
     uint16_t sample_length = DEFAULT_SAMPLE_LENGTH; 
     uint32_t duration_time = DEFAULT_DURATION_TIME; 
  
     wav->header.magic = WAV_RIFF; 
     wav->header.type = WAV_WAVE; 
     wav->format.magic = WAV_FMT; 
     wav->format.fmt_size = LE_INT(16); 
     wav->format.format = LE_SHORT(WAV_FMT_PCM); 
     wav->chunk.type = WAV_DATA; 
  
     //自定义 
     wav->format.channels = LE_SHORT(channels); 
     wav->format.sample_rate = LE_INT(sample_rate); 
     wav->format.sample_length = LE_SHORT(sample_length); 
  
 wav->format.blocks_align = LE_SHORT(channels * sample_length / 8); 
 wav->format.bytes_p_second = LE_INT((uint16_t)(wav->format.blocks_align) * sample_rate); 
      
 wav->chunk.length = LE_INT(duration_time * (uint32_t)(wav->format.bytes_p_second)); 
 wav->header.length = LE_INT((uint32_t)(wav->chunk.length) + sizeof(wav->chunk) + sizeof(wav->format) + sizeof(wav->header) - 8); 
  
     return 0; 
 } 
Пример #2
0
static void end_wave(int fd)
{				/* only close output */
	WaveChunkHeader cd;
	off64_t length_seek;
	off64_t filelen;
	u_int rifflen;

	length_seek = sizeof(WaveHeader) +
		      sizeof(WaveChunkHeader) +
		      sizeof(WaveFmtBody);
	cd.type = WAV_DATA;
	cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount);
	filelen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
	rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen);
	if (lseek64(fd, 4, SEEK_SET) == 4)
		write(fd, &rifflen, 4);
	if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
		write(fd, &cd, sizeof(WaveChunkHeader));
	if (fd != 1)
		close(fd);
}
Пример #3
0
 void SNDWAV_Play(SNDPCMContainer_t *sndpcm, WAVContainer_t *wav, int fd) 
 { 
     int load, ret; 
     off64_t written = 0; 
     off64_t c; 
     off64_t count = LE_INT(wav->chunk.length); 
  
     load = 0; 
     while (written < count) { 
         /* Must read [chunk_bytes] bytes data enough. */ 
         do { 
             c = count - written; 
             if (c > sndpcm->chunk_bytes) 
                 c = sndpcm->chunk_bytes; 
             c -= load; 
  
             if (c == 0) 
                 break; 
             ret = SNDWAV_P_SaveRead(fd, sndpcm->data_buf + load, c); 
             if (ret < 0) { 
                 fprintf(stderr, "Error safe_read/n"); 
                 exit(-1); 
             } 
             if (ret == 0) 
                 break; 
             load += ret; 
         } while ((size_t)load < sndpcm->chunk_bytes); 
  
         /* Transfer to size frame */ 
         load = load * 8 / sndpcm->bits_per_frame; 
         ret = SNDWAV_WritePcm(sndpcm, load); 
         if (ret != load) 
             break; 
          
         ret = ret * sndpcm->bits_per_frame / 8; 
         written += ret; 
         load = 0; 
     } 
 } 
Пример #4
0
// test, if it's a .WAV file, > 0 if ok (and set the speed, stereo etc.)
//                            == 0 if not
// Value returned is bytes to be discarded.
static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
{
	WaveHeader *h = (WaveHeader *)_buffer;
	u_char *buffer = NULL;
	size_t blimit = 0;
	WaveFmtBody *f;
	WaveChunkHeader *c;
	u_int type, len;

	if (size < sizeof(WaveHeader))
		return -1;
	if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
		return -1;
	if (size > sizeof(WaveHeader)) {
		check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);
		memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));
	}
	size -= sizeof(WaveHeader);
	while (1) {
		check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
		c = (WaveChunkHeader*)buffer;
		type = c->type;
		len = LE_INT(c->length);
		len += len % 2;
		if (size > sizeof(WaveChunkHeader))
			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
		size -= sizeof(WaveChunkHeader);
		if (type == WAV_FMT)
			break;
		check_wavefile_space(buffer, len, blimit);
		test_wavefile_read(fd, buffer, &size, len, __LINE__);
		if (size > len)
			memmove(buffer, buffer + len, size - len);
		size -= len;
	}

	if (len < sizeof(WaveFmtBody)) {
		error(_("unknown length of 'fmt ' chunk (read %u, should be %u at least)"),
		      len, (u_int)sizeof(WaveFmtBody));
		exit(EXIT_FAILURE);
	}
	check_wavefile_space(buffer, len, blimit);
	test_wavefile_read(fd, buffer, &size, len, __LINE__);
	f = (WaveFmtBody*) buffer;
	if (LE_SHORT(f->format) != WAV_PCM_CODE) {
		error(_("can't play not PCM-coded WAVE-files"));
		exit(EXIT_FAILURE);
	}
	if (LE_SHORT(f->modus) < 1) {
		error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->modus));
		exit(EXIT_FAILURE);
	}
	hwparams.channels = LE_SHORT(f->modus);
	switch (LE_SHORT(f->bit_p_spl)) {
	case 8:
		if (hwparams.format != DEFAULT_FORMAT &&
		    hwparams.format != SND_PCM_FORMAT_U8)
			fprintf(stderr, _("Warning: format is changed to U8\n"));
		hwparams.format = SND_PCM_FORMAT_U8;
		break;
	case 16:
		if (hwparams.format != DEFAULT_FORMAT &&
		    hwparams.format != SND_PCM_FORMAT_S16_LE)
			fprintf(stderr, _("Warning: format is changed to S16_LE\n"));
		hwparams.format = SND_PCM_FORMAT_S16_LE;
		break;
	case 24:
		switch (LE_SHORT(f->byte_p_spl) / hwparams.channels) {
		case 3:
			if (hwparams.format != DEFAULT_FORMAT &&
			    hwparams.format != SND_PCM_FORMAT_S24_3LE)
				fprintf(stderr, _("Warning: format is changed to S24_3LE\n"));
			hwparams.format = SND_PCM_FORMAT_S24_3LE;
			break;
		case 4:
			if (hwparams.format != DEFAULT_FORMAT &&
			    hwparams.format != SND_PCM_FORMAT_S24_LE)
				fprintf(stderr, _("Warning: format is changed to S24_LE\n"));
			hwparams.format = SND_PCM_FORMAT_S24_LE;
			break;
		default:
			error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),
			      LE_SHORT(f->bit_p_spl), LE_SHORT(f->byte_p_spl), hwparams.channels);
			exit(EXIT_FAILURE);
		}
		break;
	case 32:
		hwparams.format = SND_PCM_FORMAT_S32_LE;
		break;
	default:
		error(_(" can't play WAVE-files with sample %d bits wide"),
		      LE_SHORT(f->bit_p_spl));
		exit(EXIT_FAILURE);
	}
	hwparams.rate = LE_INT(f->sample_fq);
	
	if (size > len)
		memmove(buffer, buffer + len, size - len);
	size -= len;
	
	while (1) {
		u_int type, len;

		check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
		c = (WaveChunkHeader*)buffer;
		type = c->type;
		len = LE_INT(c->length);
		if (size > sizeof(WaveChunkHeader))
			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
		size -= sizeof(WaveChunkHeader);
		if (type == WAV_DATA) {
			if (len < pbrec_count && len < 0x7ffffffe)
				pbrec_count = len;
			if (size > 0)
				memcpy(_buffer, buffer, size);
			free(buffer);
			return size;
		}
		len += len % 2;
		check_wavefile_space(buffer, len, blimit);
		test_wavefile_read(fd, buffer, &size, len, __LINE__);
		if (size > len)
			memmove(buffer, buffer + len, size - len);
		size -= len;
	}

	// shouldn't be reached
	return -1;
}
Пример #5
0
/* write a WAVE-header */
static void begin_wave(int fd, size_t cnt)
{
	WaveHeader h;
	WaveFmtBody f;
	WaveChunkHeader cf, cd;
	int bits;
	u_int tmp;
	u_short tmp2;

	/* WAVE cannot handle greater than 32bit (signed?) int */
	if (cnt == (size_t)-2)
		cnt = 0x7fffff00;

	bits = 8;
	switch ((unsigned long) hwparams.format) {
	case SND_PCM_FORMAT_U8:
		bits = 8;
		break;
	case SND_PCM_FORMAT_S16_LE:
		bits = 16;
		break;
	case SND_PCM_FORMAT_S32_LE:
        case SND_PCM_FORMAT_FLOAT_LE:
		bits = 32;
		break;
	case SND_PCM_FORMAT_S24_LE:
	case SND_PCM_FORMAT_S24_3LE:
		bits = 24;
		break;
	default:
		error(_("Wave doesn't support %s format..."), snd_pcm_format_name(hwparams.format));
		exit(EXIT_FAILURE);
	}
	h.magic = WAV_RIFF;
	tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;
	h.length = LE_INT(tmp);
	h.type = WAV_WAVE;

	cf.type = WAV_FMT;
	cf.length = LE_INT(16);

        if (hwparams.format == SND_PCM_FORMAT_FLOAT_LE)
                f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT);
        else
                f.format = LE_SHORT(WAV_FMT_PCM);
	f.channels = LE_SHORT(hwparams.channels);
	f.sample_fq = LE_INT(hwparams.rate);
#if 0
	tmp2 = (samplesize == 8) ? 1 : 2;
	f.byte_p_spl = LE_SHORT(tmp2);
	tmp = dsp_speed * hwparams.channels * (u_int) tmp2;
#else
	tmp2 = hwparams.channels * snd_pcm_format_physical_width(hwparams.format) / 8;
	f.byte_p_spl = LE_SHORT(tmp2);
	tmp = (u_int) tmp2 * hwparams.rate;
#endif
	f.byte_p_sec = LE_INT(tmp);
	f.bit_p_spl = LE_SHORT(bits);

	cd.type = WAV_DATA;
	cd.length = LE_INT(cnt);

	if (write(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
	    write(fd, &cf, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader) ||
	    write(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) ||
	    write(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
		error(_("write error"));
		exit(EXIT_FAILURE);
	}
}
Пример #6
0
int SNDWAV_SetParams(SNDPCMContainer_t *sndpcm, WAVContainer_t *wav)  
{  
    snd_pcm_hw_params_t *hwparams;  
    snd_pcm_format_t format;  
    uint32_t exact_rate;  
    uint32_t buffer_time, period_time;  
  
    /* Allocate the snd_pcm_hw_params_t structure on the stack. */  
    snd_pcm_hw_params_alloca(&hwparams);  
      
    /* Init hwparams with full configuration space */  
    if (snd_pcm_hw_params_any(sndpcm->handle, hwparams) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_any/n");  
        goto ERR_SET_PARAMS;  
    }  
  
    if (snd_pcm_hw_params_set_access(sndpcm->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_set_access\n");  
        goto ERR_SET_PARAMS;  
    }  
  
    /* Set sample format */  
    if (SNDWAV_P_GetFormat(wav, &format) < 0) {  
        fprintf(stderr, "Error get_snd_pcm_format\n");  
        goto ERR_SET_PARAMS;  
    }  
    if (snd_pcm_hw_params_set_format(sndpcm->handle, hwparams, format) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_set_format\n");  
        goto ERR_SET_PARAMS;  
    }  
    sndpcm->format = format;  
  
    /* Set number of channels */  
    if (snd_pcm_hw_params_set_channels(sndpcm->handle, hwparams, LE_SHORT(wav->format.channels)) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_set_channels\n");  
        goto ERR_SET_PARAMS;  
    }  
    sndpcm->channels = LE_SHORT(wav->format.channels);  
  
    /* Set sample rate. If the exact rate is not supported */  
    /* by the hardware, use nearest possible rate.         */   
    exact_rate = LE_INT(wav->format.sample_rate);  
    if (snd_pcm_hw_params_set_rate_near(sndpcm->handle, hwparams, &exact_rate, 0) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_set_rate_near\n");  
        goto ERR_SET_PARAMS;  
    }  
    if (LE_INT(wav->format.sample_rate) != exact_rate) {  
        fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n ==> Using %d Hz instead.\n",   
            LE_INT(wav->format.sample_rate), exact_rate);  
    }  
  
    if (snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_get_buffer_time_max\n");  
        goto ERR_SET_PARAMS;  
    }  
    if (buffer_time > 500000) buffer_time = 500000;  
    period_time = buffer_time / 4;  
  
    if (snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle, hwparams, &buffer_time, 0) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_set_buffer_time_near\n");  
        goto ERR_SET_PARAMS;  
    }  
  
    if (snd_pcm_hw_params_set_period_time_near(sndpcm->handle, hwparams, &period_time, 0) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params_set_period_time_near\n");  
        goto ERR_SET_PARAMS;  
    }  
  
    /* Set hw params */  
    if (snd_pcm_hw_params(sndpcm->handle, hwparams) < 0) {  
        fprintf(stderr, "Error snd_pcm_hw_params(handle, params)\n");  
        goto ERR_SET_PARAMS;  
    }  
  
    snd_pcm_hw_params_get_period_size(hwparams, &sndpcm->chunk_size, 0);   
    snd_pcm_hw_params_get_buffer_size(hwparams, &sndpcm->buffer_size);  
    if (sndpcm->chunk_size == sndpcm->buffer_size) {        
        fprintf(stderr, ("Can't use period equal to buffer size (%lu == %lu)\n"), sndpcm->chunk_size, sndpcm->buffer_size);         
        goto ERR_SET_PARAMS;  
    }  
  
    sndpcm->bits_per_sample = snd_pcm_format_physical_width(format);  
    sndpcm->bits_per_frame = sndpcm->bits_per_sample * LE_SHORT(wav->format.channels);  
      
    sndpcm->chunk_bytes = sndpcm->chunk_size * sndpcm->bits_per_frame / 8;  
  
    /* Allocate audio data buffer */  
    sndpcm->data_buf = (uint8_t *)malloc(sndpcm->chunk_bytes);  
    if (!sndpcm->data_buf) {  
        fprintf(stderr, "Error malloc: [data_buf]\n");  
        goto ERR_SET_PARAMS;  
    }  
  
    return 0;  
  
ERR_SET_PARAMS:  
    return -1;  
}