コード例 #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
ファイル: sffile.cpp プロジェクト: Blzut3/gzdoom
static int READW(uint16_t *vp, struct timidity_file *tf)
{
	if (tf_read(vp, 2, 1, tf) != 1)
		return -1;
	*vp = LE_SHORT(*vp);
	return 1;
}
コード例 #3
0
ファイル: sndwav_common.c プロジェクト: inn1983/soundtest
int SNDWAV_P_GetFormat(WAVContainer_t *wav, snd_pcm_format_t *snd_format)  
{     
    if (LE_SHORT(wav->format.format) != WAV_FMT_PCM)  
        return -1;  
      
    switch (LE_SHORT(wav->format.sample_length)) {  
    case 16:  
        *snd_format = SND_PCM_FORMAT_S16_LE;  
        break;  
    case 8:  
        *snd_format = SND_PCM_FORMAT_U8;  
        break;  
    default:  
        *snd_format = SND_PCM_FORMAT_UNKNOWN;  
        break;  
    }  
  
    return 0;  
}  
コード例 #4
0
int CWAVInputSource::AnalyzeSource()
{
	unsigned char *p = FULL_HEADER, *priff = NULL;

	// seek to the beginning (just in case)
	m_spIO->Seek(0, FILE_BEGIN);

	// get the file size
	m_nFileBytes = m_spIO->GetSize();

	// get the RIFF header
	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_HEADER)))

	// make sure the RIFF header is valid
	if (!(p[0] == 'R' && p[1] == 'I' && p[2] == 'F' && p[3] == 'F'))
		return ERROR_INVALID_INPUT_FILE;
	p += sizeof(RIFF_HEADER);

	// read the data type header
	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(DATA_TYPE_ID_HEADER)))

	// make sure it's the right data type
	if (!(p[0] == 'W' && p[1] == 'A' && p[2] == 'V' && p[3] == 'E'))
		return ERROR_INVALID_INPUT_FILE;
	p += sizeof(DATA_TYPE_ID_HEADER);

	// find the 'fmt ' chunk
	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER)))

	while (!(p[0] == 'f' && p[1] == 'm' && p[2] == 't' && p[3] == ' '))
	{
		p += sizeof(RIFF_CHUNK_HEADER);

		// move the file pointer to the end of this chunk
		RETURN_ON_ERROR(ReadSafe(m_spIO, p, LE_LONG(p+4)))
		p += LE_LONG(p+4);

		// check again for the data chunk
		RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER)))
    }

	priff = p+4;
	p += sizeof(RIFF_CHUNK_HEADER);

	// read the format info
	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(WAV_FORMAT_HEADER)))

	// error check the header to see if we support it
	if (LE_SHORT(p) != 1)
		return ERROR_INVALID_INPUT_FILE;

	// copy the format information to the WAVEFORMATEX passed in
	FillWaveFormatEx(&m_wfeSource, LE_LONG(p+4), LE_SHORT(p+14), LE_SHORT(p+2));

	p += sizeof(WAV_FORMAT_HEADER);

	// skip over any extra data in the header
	int nWAVFormatHeaderExtra = LE_LONG(priff) - sizeof(WAV_FORMAT_HEADER);
	if (nWAVFormatHeaderExtra < 0)
		return ERROR_INVALID_INPUT_FILE;
	else {
		RETURN_ON_ERROR(ReadSafe(m_spIO, p, nWAVFormatHeaderExtra))
		p += nWAVFormatHeaderExtra;
	}

	// find the data chunk
	RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER)))

	while (!(p[0] == 'd' && p[1] == 'a' && p[2] == 't' && p[3] == 'a'))
	{
		p += sizeof(RIFF_CHUNK_HEADER);

		// move the file pointer to the end of this chunk
		RETURN_ON_ERROR(ReadSafe(m_spIO, p, LE_LONG(p+4)))
		p += LE_LONG(p+4);

		// check again for the data chunk
		RETURN_ON_ERROR(ReadSafe(m_spIO, p, sizeof(RIFF_CHUNK_HEADER)))
	}

	// we're at the data block
	m_nDataBytes = LE_LONG(p+4);
	if (m_nDataBytes < 0)
		m_nDataBytes = m_nFileBytes - m_nHeaderBytes;

	p += sizeof(RIFF_CHUNK_HEADER);

	m_nHeaderBytes = p - FULL_HEADER;

	// make sure the data bytes is a whole number of blocks
	if ((m_nDataBytes % m_wfeSource.nBlockAlign) != 0)
		return ERROR_INVALID_INPUT_FILE;

	// calculate the terminating byts
	m_nTerminatingBytes = 0;

	// we made it this far, everything must be cool
	return ERROR_SUCCESS;
}
コード例 #5
0
ファイル: play.c プロジェクト: hishamhm/protosampler
// 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;
}
コード例 #6
0
ファイル: arecord.c プロジェクト: JordanBlocher/record
/* 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);
	}
}
コード例 #7
0
ファイル: eldutils.cpp プロジェクト: JGunning/OpenAOL-TV
int ELD::update_eld(const char *buf, int size)
{
    int mnl;
    int i;

    m_e.eld_ver = GRAB_BITS(buf, 0, 3, 5);
    if (m_e.eld_ver != ELD_VER_CEA_861D &&
        m_e.eld_ver != ELD_VER_PARTIAL)
    {
        VBAUDIO(QString("Unknown ELD version %1").arg(m_e.eld_ver));
        goto out_fail;
    }

    m_e.eld_size = size;
    m_e.baseline_len    = GRAB_BITS(buf, 2, 0, 8);
    mnl                = GRAB_BITS(buf, 4, 0, 5);
    m_e.cea_edid_ver    = GRAB_BITS(buf, 4, 5, 3);

    m_e.support_hdcp    = GRAB_BITS(buf, 5, 0, 1);
    m_e.support_ai      = GRAB_BITS(buf, 5, 1, 1);
    m_e.conn_type       = GRAB_BITS(buf, 5, 2, 2);
    m_e.sad_count       = GRAB_BITS(buf, 5, 4, 4);

    m_e.aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2;
    m_e.spk_alloc       = GRAB_BITS(buf, 7, 0, 7);

    m_e.port_id         = LE_INT64(buf + 8);

    /* not specified, but the spec's tendency is little endian */
    m_e.manufacture_id  = LE_SHORT(buf + 16);
    m_e.product_id      = LE_SHORT(buf + 18);

    if (mnl > ELD_MAX_MNL)
    {
        VBAUDIO(QString("MNL is reserved value %1").arg(mnl));
        goto out_fail;
    }
    else if (ELD_FIXED_BYTES + mnl > size)
    {
        VBAUDIO(QString("out of range MNL %1").arg(mnl));
        goto out_fail;
    }
    else
    {
        strncpy(m_e.monitor_name, (char *)buf + ELD_FIXED_BYTES, mnl + 1);
        m_e.monitor_name[mnl] = '\0';
    }

    for (i = 0; i < m_e.sad_count; i++)
    {
        if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size)
        {
            VBAUDIO(QString("out of range SAD %1").arg(i));
            goto out_fail;
        }
        update_sad(i, buf + ELD_FIXED_BYTES + mnl + 3 * i);
    }

    /*
     * Assume the highest speakers configuration
     */
    if (!m_e.spk_alloc)
        m_e.spk_alloc = 0xffff;

    m_e.eld_valid = true;
    return 0;

  out_fail:
    m_e.eld_valid = false;
    return -1;
}
コード例 #8
0
ファイル: instrum.c プロジェクト: Sgt-Nukem/chocolate_duke3D
/* 
   If panning or note_to_use != -1, it will be used for all samples,
   instead of the sample-specific values in the instrument file. 

   For note_to_use, any value <0 or >127 will be forced to 0.
 
   For other parameters, 1 means yes, 0 means no, other values are
   undefined.

   TODO: do reverse loops right */
static InstrumentLayer *load_instrument(char *name, int font_type, int percussion,
				   int panning, int amp, int cfg_tuning, int note_to_use,
				   int strip_loop, int strip_envelope,
				   int strip_tail, int bank, int gm_num, int sf_ix)
{
  InstrumentLayer *lp, *lastlp, *headlp;
  Instrument *ip;
  FILE *fp;
  uint8 tmp[1024];
  int i,j,noluck=0;
#ifdef PATCH_EXT_LIST
  static char *patch_ext[] = PATCH_EXT_LIST;
#endif
  int sf2flag = 0;
  int right_samples = 0;
  int stereo_channels = 1, stereo_layer;
  int vlayer_list[19][4], vlayer, vlayer_count;

  if (!name) return 0;
  
  /* Open patch file */
  if ((fp=open_file(name, 1, OF_NORMAL)) == NULL)
    {
      noluck=1;
#ifdef PATCH_EXT_LIST
      /* Try with various extensions */
      for (i=0; patch_ext[i]; i++)
	{
	  if (strlen(name)+strlen(patch_ext[i])<1024)
	    {
              char path[1024];
	      strcpy(path, name);
	      strcat(path, patch_ext[i]);
	      if ((fp=open_file(path, 1, OF_NORMAL)) != NULL)
		{
		  noluck=0;
		  break;
		}
	    }
	}
#endif
    }
  
  if (noluck)
    {
      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
		"Instrument `%s' can't be found.", name);
      return 0;
    }
      
  /*ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);*/
  
  /* Read some headers and do cursory sanity checks. There are loads
     of magic offsets. This could be rewritten... */

  if ((239 != fread(tmp, 1, 239, fp)) ||
      (memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
       memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
						      differences are */
    {
      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
      return 0;
    }

/* patch layout:
 * bytes:  info:		starts at offset:
 * 22	id (see above)		0
 * 60	copyright		22
 *  1	instruments		82
 *  1	voices			83
 *  1	channels		84
 *  2	number of waveforms	85
 *  2	master volume		87
 *  4	datasize		89
 * 36   reserved, but now:	93
 * 	7 "SF2EXT\0" id			93
 * 	1 right samples		       100
 *     28 reserved		       101
 *  2	instrument number	129
 * 16	instrument name		131
 *  4	instrument size		147
 *  1	number of layers	151
 * 40	reserved		152
 *  1	layer duplicate		192
 *  1	layer number		193
 *  4	layer size		194
 *  1	number of samples	198
 * 40	reserved		199
 * 				239
 * THEN, for each sample, see below
 */

  if (!memcmp(tmp + 93, "SF2EXT", 6))
    {
	    sf2flag = 1;
	    vlayer_count = tmp[152];
    }

  if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 
				       0 means 1 */
    {
      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
	   "Can't handle patches with %d instruments", tmp[82]);
      return 0;
    }

  if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
    {
      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
	   "Can't handle instruments with %d layers", tmp[151]);
      return 0;
    }
  

  if (sf2flag && vlayer_count > 0) {
	for (i = 0; i < 9; i++)
	  for (j = 0; j < 4; j++)
	    vlayer_list[i][j] = tmp[153+i*4+j];
	for (i = 9; i < 19; i++)
	  for (j = 0; j < 4; j++)
	    vlayer_list[i][j] = tmp[199+(i-9)*4+j];
  }
  else {
	for (i = 0; i < 19; i++)
	  for (j = 0; j < 4; j++)
	    vlayer_list[i][j] = 0;
	vlayer_list[0][0] = 0;
	vlayer_list[0][1] = 127;
	vlayer_list[0][2] = tmp[198];
	vlayer_list[0][3] = 0;
	vlayer_count = 1;
  }

  lastlp = 0;

  for (vlayer = 0; vlayer < vlayer_count; vlayer++) {

  lp=(InstrumentLayer *)safe_malloc(sizeof(InstrumentLayer));
  lp->size = sizeof(InstrumentLayer);
  lp->lo = vlayer_list[vlayer][0];
  lp->hi = vlayer_list[vlayer][1];
  ip=(Instrument *)safe_malloc(sizeof(Instrument));
  lp->size += sizeof(Instrument);
  lp->instrument = ip;
  lp->next = 0;

  if (lastlp) lastlp->next = lp;
  else headlp = lp;

  lastlp = lp;

  if (sf2flag) ip->type = INST_SF2;
  else ip->type = INST_GUS;
  ip->samples = vlayer_list[vlayer][2];
  ip->sample = (Sample *)safe_malloc(sizeof(Sample) * ip->samples);
  lp->size += sizeof(Sample) * ip->samples;
  ip->left_samples = ip->samples;
  ip->left_sample = ip->sample;
  right_samples = vlayer_list[vlayer][3];
  ip->right_samples = right_samples;
  if (right_samples)
    {
      ip->right_sample = (Sample *)safe_malloc(sizeof(Sample) * right_samples);
      lp->size += sizeof(Sample) * right_samples;
      stereo_channels = 2;
    }
  else ip->right_sample = 0;
  ip->contents = 0;

  ctl->cmsg(CMSG_INFO, VERB_NOISY, "%s%s[%d,%d] %s(%d-%d layer %d of %d)",
	(percussion)? "   ":"", name,
	(percussion)? note_to_use : gm_num, bank,
	(right_samples)? "(2) " : "",
	lp->lo, lp->hi, vlayer+1, vlayer_count);

 for (stereo_layer = 0; stereo_layer < stereo_channels; stereo_layer++)
 {
  int sample_count;

  if (stereo_layer == 0) sample_count = ip->left_samples;
  else if (stereo_layer == 1) sample_count = ip->right_samples;

  for (i=0; i < sample_count; i++)
    {
      uint8 fractions;
      int32 tmplong;
      uint16 tmpshort;
      uint16 sample_volume;
      uint8 tmpchar;
      Sample *sp;
      uint8 sf2delay;

#define READ_CHAR(thing) \
      if (1 != fread(&tmpchar, 1, 1, fp)) goto fail; \
      thing = tmpchar;
#define READ_SHORT(thing) \
      if (1 != fread(&tmpshort, 2, 1, fp)) goto fail; \
      thing = LE_SHORT(tmpshort);
#define READ_LONG(thing) \
      if (1 != fread(&tmplong, 4, 1, fp)) goto fail; \
      thing = LE_LONG(tmplong);

/*
 *  7	sample name
 *  1	fractions
 *  4	length
 *  4	loop start
 *  4	loop end
 *  2	sample rate
 *  4	low frequency
 *  4	high frequency
 *  2	finetune
 *  1	panning
 *  6	envelope rates			|
 *  6	envelope offsets		|  18 bytes
 *  3	tremolo sweep, rate, depth	|
 *  3	vibrato sweep, rate, depth	|
 *  1	sample mode
 *  2	scale frequency
 *  2	scale factor
 *  2	sample volume (??)
 * 34	reserved
 * Now: 1	delay
 * 	33	reserved
 */
      skip(fp, 7); /* Skip the wave name */

      if (1 != fread(&fractions, 1, 1, fp))
	{
	fail:
	  ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
	  if (stereo_layer == 1)
	     {
	       for (j=0; j<i; j++)
	         free(ip->right_sample[j].data);
	       free(ip->right_sample);
	       i = ip->left_samples;
	     }
	  for (j=0; j<i; j++)
	    free(ip->left_sample[j].data);
	  free(ip->left_sample);
	  free(ip);
	  free(lp);
	  return 0;
	}

      if (stereo_layer == 0) sp=&(ip->left_sample[i]);
      else if (stereo_layer == 1) sp=&(ip->right_sample[i]);

      READ_LONG(sp->data_length);
      READ_LONG(sp->loop_start);
      READ_LONG(sp->loop_end);
      READ_SHORT(sp->sample_rate);
      READ_LONG(sp->low_freq);
      READ_LONG(sp->high_freq);
      READ_LONG(sp->root_freq);
      skip(fp, 2); /* Why have a "root frequency" and then "tuning"?? */
      
      READ_CHAR(tmp[0]);

      if (panning==-1)
	sp->panning = (tmp[0] * 8 + 4) & 0x7f;
      else
	sp->panning=(uint8)(panning & 0x7F);

      sp->resonance=0;
      sp->cutoff_freq=0;
      sp->reverberation=0;
      sp->chorusdepth=0;
      sp->exclusiveClass=0;
      sp->keyToModEnvHold=0;
      sp->keyToModEnvDecay=0;
      sp->keyToVolEnvHold=0;
      sp->keyToVolEnvDecay=0;

      if (cfg_tuning)
	{
	  double tune_factor = (double)(cfg_tuning)/1200.0;
	  tune_factor = pow(2.0, tune_factor);
	  sp->root_freq = (uint32)( tune_factor * (double)sp->root_freq );
	}

      /* envelope, tremolo, and vibrato */
      if (18 != fread(tmp, 1, 18, fp)) goto fail; 

      if (!tmp[13] || !tmp[14])
	{
	  sp->tremolo_sweep_increment=
	    sp->tremolo_phase_increment=sp->tremolo_depth=0;
	  ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
	}
      else
	{
	  sp->tremolo_sweep_increment=convert_tremolo_sweep(tmp[12]);
	  sp->tremolo_phase_increment=convert_tremolo_rate(tmp[13]);
	  sp->tremolo_depth=tmp[14];
	  ctl->cmsg(CMSG_INFO, VERB_DEBUG,
	       " * tremolo: sweep %d, phase %d, depth %d",
	       sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
	       sp->tremolo_depth);
	}

      if (!tmp[16] || !tmp[17])
	{
	  sp->vibrato_sweep_increment=
	    sp->vibrato_control_ratio=sp->vibrato_depth=0;
	  ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
	}
      else
	{
	  sp->vibrato_control_ratio=convert_vibrato_rate(tmp[16]);
	  sp->vibrato_sweep_increment=
	    convert_vibrato_sweep(tmp[15], sp->vibrato_control_ratio);
	  sp->vibrato_depth=tmp[17];
	  ctl->cmsg(CMSG_INFO, VERB_DEBUG,
	       " * vibrato: sweep %d, ctl %d, depth %d",
	       sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
	       sp->vibrato_depth);

	}

      READ_CHAR(sp->modes);
      READ_SHORT(sp->freq_center);
      READ_SHORT(sp->freq_scale);

      if (sf2flag)
        {
          READ_SHORT(sample_volume);
	  READ_CHAR(sf2delay);
          READ_CHAR(sp->exclusiveClass);
          skip(fp, 32);
	}
      else
        {
          skip(fp, 36);
        }

      /* Mark this as a fixed-pitch instrument if such a deed is desired. */
      if (note_to_use!=-1)
	sp->note_to_use=(uint8)(note_to_use);
      else
	sp->note_to_use=0;
      
      /* seashore.pat in the Midia patch set has no Sustain. I don't
         understand why, and fixing it by adding the Sustain flag to
         all looped patches probably breaks something else. We do it
         anyway. */
	 
      if (sp->modes & MODES_LOOPING) 
	sp->modes |= MODES_SUSTAIN;

      /* Strip any loops and envelopes we're permitted to */
      if ((strip_loop==1) && 
	  (sp->modes & (MODES_SUSTAIN | MODES_LOOPING | 
			MODES_PINGPONG | MODES_REVERSE)))
	{
	  ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
	  sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | 
			MODES_PINGPONG | MODES_REVERSE);
	}

      if (strip_envelope==1)
	{
	  if (sp->modes & MODES_ENVELOPE)
	    ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
	  sp->modes &= ~MODES_ENVELOPE;
	}
      else if (strip_envelope != 0)
	{
	  /* Have to make a guess. */
	  if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
	    {
	      /* No loop? Then what's there to sustain? No envelope needed
		 either... */
	      sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
	      ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
			" - No loop, removing sustain and envelope");
	    }
	  else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100) 
	    {
	      /* Envelope rates all maxed out? Envelope end at a high "offset"?
		 That's a weird envelope. Take it out. */
	      sp->modes &= ~MODES_ENVELOPE;
	      ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
			" - Weirdness, removing envelope");
	    }
	  else if (!(sp->modes & MODES_SUSTAIN))
	    {
	      /* No sustain? Then no envelope.  I don't know if this is
		 justified, but patches without sustain usually don't need the
		 envelope either... at least the Gravis ones. They're mostly
		 drums.  I think. */
	      sp->modes &= ~MODES_ENVELOPE;
	      ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
			" - No sustain, removing envelope");
	    }
	}

      sp->attenuation = 0;

      for (j=ATTACK; j<DELAY; j++)
	{
	  sp->envelope_rate[j]=
	    (j<3)? convert_envelope_rate_attack(tmp[j], 11) : convert_envelope_rate(tmp[j]);
	  sp->envelope_offset[j]= 
	    convert_envelope_offset(tmp[6+j]);
	}
      if (sf2flag)
	{
	  if (sf2delay > 5) sf2delay = 5;
	  sp->envelope_rate[DELAY] = (int32)( (sf2delay*play_mode->rate) / 1000 );
	}
      else
	{
          sp->envelope_rate[DELAY]=0;
	}
      sp->envelope_offset[DELAY]=0;

      for (j=ATTACK; j<DELAY; j++)
	{
	  sp->modulation_rate[j]=sp->envelope_rate[j];
	  sp->modulation_offset[j]=sp->envelope_offset[j];
	}
      sp->modulation_rate[DELAY] = sp->modulation_offset[DELAY] = 0;
      sp->modEnvToFilterFc=0;
      sp->modEnvToPitch=0;
      sp->lfo_sweep_increment = 0;
      sp->lfo_phase_increment = 0;
      sp->modLfoToFilterFc = 0;
      sp->vibrato_delay = 0;

      /* Then read the sample data */
      if (sp->data_length/2 > MAX_SAMPLE_SIZE)
        {
	  goto fail;
	}
      sp->data = safe_malloc(sp->data_length + 1);
      lp->size += sp->data_length + 1;

      if (1 != fread(sp->data, sp->data_length, 1, fp))
	goto fail;
      
      if (!(sp->modes & MODES_16BIT)) /* convert to 16-bit data */
	{
	  int32 i=sp->data_length;
	  uint8 *cp=(uint8 *)(sp->data);
	  uint16 *tmp,*newdta;
	  tmp=newdta=safe_malloc(sp->data_length*2 + 2);
	  while (i--)
	    *tmp++ = (uint16)(*cp++) << 8;
	  cp=(uint8 *)(sp->data);
	  sp->data = (sample_t *)newdta;
	  free(cp);
	  sp->data_length *= 2;
	  sp->loop_start *= 2;
	  sp->loop_end *= 2;
	}
#ifndef LITTLE_ENDIAN
      else
	/* convert to machine byte order */
	{
	  int32 i=sp->data_length/2;
	  int16 *tmp=(int16 *)sp->data,s;
	  while (i--)
	    { 
	      s=LE_SHORT(*tmp);
	      *tmp++=s;
	    }
	}
#endif
      
      if (sp->modes & MODES_UNSIGNED) /* convert to signed data */
	{
	  int32 i=sp->data_length/2;
	  int16 *tmp=(int16 *)sp->data;
	  while (i--)
	    *tmp++ ^= 0x8000;
	}

      /* Reverse reverse loops and pass them off as normal loops */
      if (sp->modes & MODES_REVERSE)
	{
	  int32 t;
	  /* The GUS apparently plays reverse loops by reversing the
	     whole sample. We do the same because the GUS does not SUCK. */

	  ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
	  reverse_data((int16 *)sp->data, 0, sp->data_length/2);

	  t=sp->loop_start;
	  sp->loop_start=sp->data_length - sp->loop_end;
	  sp->loop_end=sp->data_length - t;

	  sp->modes &= ~MODES_REVERSE;
	  sp->modes |= MODES_LOOPING; /* just in case */
	}

      /* If necessary do some anti-aliasing filtering  */

      if (antialiasing_allowed)
	  antialiasing(sp,play_mode->rate);

#ifdef ADJUST_SAMPLE_VOLUMES
      if (amp!=-1)
	sp->volume=(FLOAT_T)((amp) / 100.0);
      else if (sf2flag)
	sp->volume=(FLOAT_T)((sample_volume) / 255.0);
      else
	{
	  /* Try to determine a volume scaling factor for the sample.
	     This is a very crude adjustment, but things sound more
	     balanced with it. Still, this should be a runtime option. */
	  uint32 i, numsamps=sp->data_length/2;
	  uint32 higher=0, highcount=0;
	  int16 maxamp=0,a;
	  int16 *tmp=(int16 *)sp->data;
	  i = numsamps;
	  while (i--)
	    {
	      a=*tmp++;
	      if (a<0) a=-a;
	      if (a>maxamp)
		maxamp=a;
	    }
	  tmp=(int16 *)sp->data;
	  i = numsamps;
	  while (i--)
	    {
	      a=*tmp++;
	      if (a<0) a=-a;
	      if (a > 3*maxamp/4)
		{
		   higher += a;
		   highcount++;
		}
	    }
	  if (highcount) higher /= highcount;
	  else higher = 10000;
	  sp->volume = (32768.0 * 0.875) /  (double)higher ;
	  ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
	}
#else
      if (amp!=-1)
	sp->volume=(double)(amp) / 100.0;
      else
	sp->volume=1.0;
#endif

      sp->data_length /= 2; /* These are in bytes. Convert into samples. */

      sp->loop_start /= 2;
      sp->loop_end /= 2;
      sp->data[sp->data_length] = sp->data[sp->data_length-1];

      /* Then fractional samples */
      sp->data_length <<= FRACTION_BITS;
      sp->loop_start <<= FRACTION_BITS;
      sp->loop_end <<= FRACTION_BITS;

    /* trim off zero data at end */
    {
	int ls = sp->loop_start>>FRACTION_BITS;
	int le = sp->loop_end>>FRACTION_BITS;
	int se = sp->data_length>>FRACTION_BITS;
	while (se > 1 && !sp->data[se-1]) se--;
	if (le > se) le = se;
	if (ls >= le) sp->modes &= ~MODES_LOOPING;
	sp->loop_end = le<<FRACTION_BITS;
	sp->data_length = se<<FRACTION_BITS;
    }

      /* Adjust for fractional loop points. This is a guess. Does anyone
	 know what "fractions" really stands for? */
      sp->loop_start |=
	(fractions & 0x0F) << (FRACTION_BITS-4);
      sp->loop_end |=
	((fractions>>4) & 0x0F) << (FRACTION_BITS-4);

      /* If this instrument will always be played on the same note,
	 and it's not looped, we can resample it now. */
      if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
	pre_resample(sp);

#ifdef LOOKUP_HACK
      /* Squash the 16-bit data into 8 bits. */
      {
	uint8 *gulp,*ulp;
	int16 *swp;
	int l=sp->data_length >> FRACTION_BITS;
	gulp=ulp=safe_malloc(l+1);
	swp=(int16 *)sp->data;
	while(l--)
	  *ulp++ = (*swp++ >> 8) & 0xFF;
	free(sp->data);
	sp->data=(sample_t *)gulp;
      }
#endif
      
      if (strip_tail==1)
	{
	  /* Let's not really, just say we did. */
	  ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
	  sp->data_length = sp->loop_end;
	}
    } /* end of sample loop */
 } /* end of stereo layer loop */
 } /* end of vlayer loop */


  close_file(fp);
  return headlp;
}
コード例 #9
0
ファイル: wav2pat.c プロジェクト: gitpan/MIDI-SoundFont
int main(int argc, char **argv)
{
  int32
    note=DEFAULT_NOTE,
    root=DEFAULT_ROOT,
    verbosity=0,
    samplerate=-1,
    datasize=-1,
    junklength, c;

  int
    infd=STDIN_FILENO;

  unsigned char
    thing[4096],
    *point,
    modes=0;

#ifdef __MACOS__
  mac_main_wav2pat(&root, &note, &infd);
#else

  while ((c=getopt(argc, argv, "r:n:vh"))>0)
    switch(c)
      {
      case 'r': root=atol(optarg); break;
      case 'n': root=freq_table[atoi(optarg) & 127]; break;
      case 'u': note=atol(optarg); break;
      case 'v': verbosity++; break;
      case 'h': usage(); return 0;
      default: return 1;
      }

  if (optind==argc-1)
    {
      if ((infd=open(argv[optind], O_RDONLY))<0)
	{
	  perror("wav2pat: I can't open your WAVE");
	  return 3;
	}
    }
  else if (optind!=argc)
    {
	usage();
	return 1;
    }
#endif

  /* check out the putative RIFF WAVE on stdin */

  if (read(infd, thing, 12)<=0)
    {
      perror("wav2pat: I can't read your WAVE");
      return 3;
    }

  if (memcmp(thing, "RIFF", 4) || memcmp(thing+8, "WAVE", 4))
    {
      fprintf(stderr, "wav2pat: I want a RIFF WAVE on stdin!" NLS);
      return 2;
    }

  while (datasize==-1)
    {
      if (read(infd, thing, 8)!=8)
	{
	  perror("wav2pat: "
		 "Your WAVE ran out before I got to the interesting bits");
	  return 3;
	}
      junklength=LE_LONG(*((int32 *)(thing+4)));

      /* This Microsoft file format is designed to be impossible to
	 parse correctly if one doesn't have the full specification.
	 If you have a wave with an INFO "chunk", you lose. Thank you
	 for playing. */

      if (!memcmp(thing, "fmt ", 4))
	{
	  if (junklength > 4096)
	    {
	      fprintf(stderr, "wav2pat: "
		      "WAVEs with %ld-byte format blocks make me throw up!"
		      NLS,
		      junklength);
	      return 2;
	    }
	  if (read(infd, thing, junklength) != junklength)
	    {
	      perror("wav2pat: Your WAVE is mangled");
	      return 3;
	    }
	  if (LE_SHORT(*((int16 *)(thing))) != 1)
	    {
	      fprintf(stderr, "wav2pat: I don't understand your WAVE. "
		      "It has a type %d format chunk!" NLS,
		      LE_SHORT(*((int16 *)(thing))));
	      return 2;
	    }
	  if (LE_SHORT(*((int16 *)(thing + 2))) != 1)
	    {
	      fprintf(stderr, "wav2pat: This WAVE has %d channels! "
		      "There can be only one!" NLS,
		      LE_SHORT(*((int16 *)(thing + 2))));
	      return 2;
	    }
	  samplerate=LE_LONG(*((int32 *)(thing + 4)));
	  switch(LE_SHORT(*((int16 *)(thing + 14))))
	    {
	    case 8: modes |= MODES_UNSIGNED; break;
	    case 16: modes |= MODES_16BIT; break;
	    default:
	      fprintf(stderr, "wav2pat: Ack! Ppthbth! %d-bit samples!",
		      LE_SHORT(*((int16 *)(thing + 14))));
	      return 2;
	    }
	  if (verbosity)
	    fprintf(stderr, "wav2pat: This is a %d-bit, %ld Hz WAVE" NLS,
		    (LE_SHORT(*((int16 *)(thing + 14)))),
		    samplerate);
	}
      else if (!memcmp(thing, "data", 4))
	{
	  if (samplerate==-1)
	    {
	      fprintf(stderr, "wav2pat: Your WAVE has no format information before data!" NLS);
	      return 2;
	    }
	  if (verbosity)
	    fprintf(stderr, "wav2pat: It has %ld bytes of data" NLS, junklength);
	  datasize=junklength;
	}
      else
	{
	  if (verbosity)
	    fprintf(stderr, "wav2pat: "
		    "Your WAVE has a %ld-byte chunk called `%4.4s'" NLS,
		    junklength, thing);

	  /* It's cool to pad chunks with NULs to align them on
             half-word boundaries. */
	  if (junklength & 1)
	    junklength++;

	  while (junklength>0)
	    {
	      if ((c=read(infd, thing, (junklength>4096) ? 4096 : junklength))
		  <= 0)
		{
		  perror("wav2pat: Now your WAVE has run out of data");
		  return 3;
		}
	      junklength -= c;
	    }
	}
    }

  /* hammer together something that looks like a GUS patch header */

#define pound(a) *point++=(a);
#define pounds(a) { int16 x = (int16)LE_SHORT(a); memcpy(point, &x, 2); point+=2; }
#define poundl(a) { int32 x = LE_LONG(a);  memcpy(point, &x, 4); point+=4; }
#define bounce(a) point += a;

  memset(thing, 0, 335);
  point=thing;

  /* header */
  memcpy(point, "GF1PATCH110", 12);
  point += 12;

  /* Gravis ID */
  memcpy(point, "ID#000002", 10);
  point += 10;

  /* description */
  strcpy((char *)point, "Copyleft 1995 EWE&U Conductions and one Retreated Gravi\032");
  point += 60;

  pound(1); /* instruments */
  pound(14); /* voices */
  pound(0); /* channels */
  pounds(1); /* waveforms */
  pounds(127); /* master volume */
  poundl(datasize); /* data size */
  bounce(36); /* reserved */

  pounds(1); /* instrument # */
  strcpy((char *)point, "Bleahnoise"); /* instrument name */
  point += 16;
  poundl(datasize); /* instrument size */
  pound(1); /* layers */
  bounce(40); /* reserved */

  pound(0); /* layer duplicate */
  pound(0); /* layer */
  poundl(datasize); /* layer size */
  pound(1); /* samples */
  bounce(40); /* reserved */

  strcpy((char *)point, "bleah"); /* wave name */
  point += 7;
  pound(0); /* fractions */
  poundl(datasize); /* wave size */
  poundl(0); /* loop start */
  poundl(datasize); /* loop end */
  pounds(samplerate); /* sample rate */
  poundl(8176); /* low freq */
  poundl(12543854); /* high freq */
  poundl(root); /* root freq */
  pounds(512); /* tune */
  pound(7);  /* balance */

  pound(63); /* envelope rates */
  pound(63);
  pound(63);
  pound(63);
  pound(63);
  pound(63);

  pound(240); /* envelope offsets */
  pound(240);
  pound(240);
  pound(240);
  pound(240);
  pound(240);

  pound(0); /* tremolo sweep */
  pound(0); /* tremolo rate */
  pound(0); /* tremolo depth */
  pound(0); /* vibrato sweep */
  pound(0); /* vibrato rate */
  pound(0); /* vibrato depth */

  pound(modes); /* modes */

  pounds(note); /* scale freq */
  pounds(1024); /* scale factor */
  bounce(36); /* reserved */

  write(STDOUT_FILENO, thing, 335);

  /* wave data */

  while (datasize>0)
    {
      if ((c=read(infd, thing, (datasize>4096) ? 4096 : datasize))
	  <= 0)
	{
	  perror("wav2pat: I can't read data");
	  return 3;
	}
      write(STDOUT_FILENO, thing, c);
      datasize -= c;
    }

  /* be courteous */
  if (infd != STDIN_FILENO)
    close(infd);

  return 0;
}
コード例 #10
0
/* 
 If panning or note_to_use != -1, it will be used for all samples,
 instead of the sample-specific values in the instrument file. 

 For note_to_use, any value <0 or >127 will be forced to 0.

 For other parameters, 1 means yes, 0 means no, other values are
 undefined.

 TODO: do reverse loops right */
static Instrument *load_instrument(char *name, int percussion,
                                   int panning, int amp, int note_to_use,
                                   int strip_loop, int strip_envelope,
                                   int strip_tail)
{
	ignore_unused_variable_warning(percussion);
	Instrument *ip;
	Sample *sp;
	FILE *fp;
	uint8 tmp[1024];
	int i,j,noluck=0;
#ifdef PATCH_EXT_LIST
	static const char *patch_ext[] = PATCH_EXT_LIST;
#endif

	if (!name) return 0;

	/* Open patch file */
	if ((fp=open_file(name, 1, OF_NORMAL)) == NULL)
	{
		noluck=1;
#ifdef PATCH_EXT_LIST
		/* Try with various extensions */
		for (i=0; patch_ext[i]; i++)
		{
			if (strlen(name)+strlen(patch_ext[i])<1024)
			{
				char path[1024];
				strcpy(path, name);
				strcat(path, patch_ext[i]);
				if ((fp=open_file(path, 1, OF_NORMAL)) != NULL)
				{
					noluck=0;
					break;
				}
			}
		}
#endif
	}

	if (noluck)
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
		          "Instrument `%s' can't be found.", name);
		return 0;
	}

	ctl->cmsg(CMSG_INFO, VERB_NOISY, "Loading instrument %s", current_filename);

	/* Read some headers and do cursory sanity checks. There are loads
	 of magic offsets. This could be rewritten... */

	if ((239 != fread(tmp, 1, 239, fp)) ||
	    (memcmp(tmp, "GF1PATCH110\0ID#000002", 22) &&
	     memcmp(tmp, "GF1PATCH100\0ID#000002", 22))) /* don't know what the
		 differences are */
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: not an instrument", name);
		return 0;
	}

	if (tmp[82] != 1 && tmp[82] != 0) /* instruments. To some patch makers, 
		 0 means 1 */
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
		          "Can't handle patches with %d instruments", tmp[82]);
		return 0;
	}

	if (tmp[151] != 1 && tmp[151] != 0) /* layers. What's a layer? */
	{
		ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
		          "Can't handle instruments with %d layers", tmp[151]);
		return 0;
	}

	ip=safe_Malloc<Instrument>();
	ip->samples = tmp[198];
	ip->sample = safe_Malloc<Sample>(ip->samples);
	for (i=0; i<ip->samples; i++)
	{

		uint8 fractions;
		sint32 tmplong;
		uint16 tmpshort;
		uint8 tmpchar;

#define READ_CHAR(thing) \
		if (1 != fread(&tmpchar, 1, 1, fp)) goto fail; \
		thing = tmpchar;
#define READ_SHORT(thing) \
		if (1 != fread(&tmpshort, 2, 1, fp)) goto fail; \
		thing = LE_SHORT(tmpshort);
#define READ_LONG(thing) \
		if (1 != fread(&tmplong, 4, 1, fp)) goto fail; \
		thing = LE_LONG(tmplong);

		skip(fp, 7); /* Skip the wave name */

		if (1 != fread(&fractions, 1, 1, fp))
		{
		fail:
			ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Error reading sample %d", i);
			for (j=0; j<i; j++)
				free(ip->sample[j].data);
			free(ip->sample);
			free(ip);
			return 0;
		}

		sp=&(ip->sample[i]);

		READ_LONG(sp->data_length);
		READ_LONG(sp->loop_start);
		READ_LONG(sp->loop_end);
		READ_SHORT(sp->sample_rate);
		READ_LONG(sp->low_freq);
		READ_LONG(sp->high_freq);
		READ_LONG(sp->root_freq);
		skip(fp, 2); /* Why have a "root frequency" and then "tuning"?? */

		READ_CHAR(tmp[0]);

		if (panning==-1)
			sp->panning = (tmp[0] * 8 + 4) & 0x7f;
		else
			sp->panning=static_cast<uint8>(panning & 0x7F);

		/* envelope, tremolo, and vibrato */
		if (18 != fread(tmp, 1, 18, fp)) goto fail; 

		if (!tmp[13] || !tmp[14])
		{
			sp->tremolo_sweep_increment=
				sp->tremolo_phase_increment=sp->tremolo_depth=0;
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no tremolo");
		}
		else
		{
			sp->tremolo_sweep_increment=convert_tremolo_sweep(tmp[12]);
			sp->tremolo_phase_increment=convert_tremolo_rate(tmp[13]);
			sp->tremolo_depth=tmp[14];
			ctl->cmsg(CMSG_INFO, VERB_DEBUG,
			          " * tremolo: sweep %d, phase %d, depth %d",
			          sp->tremolo_sweep_increment, sp->tremolo_phase_increment,
			          sp->tremolo_depth);
		}

		if (!tmp[16] || !tmp[17])
		{
			sp->vibrato_sweep_increment=
				sp->vibrato_control_ratio=sp->vibrato_depth=0;
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * no vibrato");
		}
		else
		{
			sp->vibrato_control_ratio=convert_vibrato_rate(tmp[16]);
			sp->vibrato_sweep_increment=
				convert_vibrato_sweep(tmp[15], sp->vibrato_control_ratio);
			sp->vibrato_depth=tmp[17];
			ctl->cmsg(CMSG_INFO, VERB_DEBUG,
			          " * vibrato: sweep %d, ctl %d, depth %d",
			          sp->vibrato_sweep_increment, sp->vibrato_control_ratio,
			          sp->vibrato_depth);
		}

		READ_CHAR(sp->modes);

		skip(fp, 40); /* skip the useless scale frequency, scale factor
		 (what's it mean?), and reserved space */

		/* Mark this as a fixed-pitch instrument if such a deed is desired. */
		if (note_to_use!=-1)
			sp->note_to_use=static_cast<uint8>(note_to_use);
		else
			sp->note_to_use=0;

		/* seashore.pat in the Midia patch set has no Sustain. I don't
		 understand why, and fixing it by adding the Sustain flag to
		 all looped patches probably breaks something else. We do it
		 anyway. */

		if (sp->modes & MODES_LOOPING) 
			sp->modes |= MODES_SUSTAIN;

		/* Strip any loops and envelopes we're permitted to */
		if ((strip_loop==1) && 
		    (sp->modes & (MODES_SUSTAIN | MODES_LOOPING | 
		                  MODES_PINGPONG | MODES_REVERSE)))
		{
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing loop and/or sustain");
			sp->modes &=~(MODES_SUSTAIN | MODES_LOOPING | 
			              MODES_PINGPONG | MODES_REVERSE);
		}

		if (strip_envelope==1)
		{
			if (sp->modes & MODES_ENVELOPE)
				ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Removing envelope");
			sp->modes &= ~MODES_ENVELOPE;
		}
		else if (strip_envelope != 0)
		{
			/* Have to make a guess. */
			if (!(sp->modes & (MODES_LOOPING | MODES_PINGPONG | MODES_REVERSE)))
			{
				/* No loop? Then what's there to sustain? No envelope needed
				 either... */
				sp->modes &= ~(MODES_SUSTAIN|MODES_ENVELOPE);
				ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
				          " - No loop, removing sustain and envelope");
			}
			else if (!memcmp(tmp, "??????", 6) || tmp[11] >= 100) 
			{
				/* Envelope rates all maxed out? Envelope end at a high "offset"?
				 That's a weird envelope. Take it out. */
				sp->modes &= ~MODES_ENVELOPE;
				ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
				          " - Weirdness, removing envelope");
			}
			else if (!(sp->modes & MODES_SUSTAIN))
			{
				/* No sustain? Then no envelope.  I don't know if this is
				 justified, but patches without sustain usually don't need the
				 envelope either... at least the Gravis ones. They're mostly
				 drums.  I think. */
				sp->modes &= ~MODES_ENVELOPE;
				ctl->cmsg(CMSG_INFO, VERB_DEBUG, 
				          " - No sustain, removing envelope");
			}
		}

		for (j=0; j<6; j++)
		{
			sp->envelope_rate[j]=
				convert_envelope_rate(tmp[j]);
			sp->envelope_offset[j]= 
				convert_envelope_offset(tmp[6+j]);
		}

		/* Then read the sample data */
		sp->data = safe_Malloc<sample_t>(sp->data_length);
		if (1 != fread(sp->data, sp->data_length, 1, fp))
			goto fail;

		if (!(sp->modes & MODES_16BIT)) /* convert to 16-bit data */
		{
			sint32 i=sp->data_length;
			uint8 *cp=reinterpret_cast<uint8 *>(sp->data);
			uint16 *tmp,*new_dat;
			tmp=new_dat=safe_Malloc<uint16>(sp->data_length);
			while (i--)
				*tmp++ = static_cast<uint16>(*cp++) << 8;
			cp=reinterpret_cast<uint8 *>(sp->data);
			sp->data = reinterpret_cast<sample_t *>(new_dat);
			free(cp);
			sp->data_length *= 2;
			sp->loop_start *= 2;
			sp->loop_end *= 2;
		}
#ifndef TIMIDITY_LITTLE_ENDIAN
		else
			/* convert to machine byte order */
		{
			sint32 i=sp->data_length/2;
			sint16 *tmp=reinterpret_cast<sint16 *>(sp->data),s;
			while (i--)
			{ 
				s=LE_SHORT(*tmp);
				*tmp++=s;
			}
		}
#endif

		if (sp->modes & MODES_UNSIGNED) /* convert to signed data */
		{
			sint32 i=sp->data_length/2;
			sint16 *tmp = sp->data;
			while (i--)
				*tmp++ ^= 0x8000;
		}

		/* Reverse reverse loops and pass them off as normal loops */
		if (sp->modes & MODES_REVERSE)
		{
			sint32 t;
			/* The GUS apparently plays reverse loops by reversing the
			 whole sample. We do the same because the GUS does not SUCK. */

			ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Reverse loop in %s", name);
			reverse_data(sp->data, 0, sp->data_length/2);

			t=sp->loop_start;
			sp->loop_start=sp->data_length - sp->loop_end;
			sp->loop_end=sp->data_length - t;

			sp->modes &= ~MODES_REVERSE;
			sp->modes |= MODES_LOOPING; /* just in case */
		}

		/* If necessary do some anti-aliasing filtering  */

		if (antialiasing_allowed)
			antialiasing(sp,play_mode->rate);

#ifdef ADJUST_SAMPLE_VOLUMES
		if (amp!=-1)
			sp->volume=static_cast<float>((amp) / 100.0);
		else
		{
			/* Try to determine a volume scaling factor for the sample.
			 This is a very crude adjustment, but things sound more
			 balanced with it. Still, this should be a runtime option. */
			sint32 i=sp->data_length/2;
			sint16 maxamp=0,a;
			sint16 *tmp = sp->data;
			while (i--)
			{
				a=*tmp++;
				if (a<0) a=-a;
				if (a>maxamp)
					maxamp=a;
			}
			sp->volume=static_cast<float>(32768.0 / maxamp);
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " * volume comp: %f", sp->volume);
		}
#else
		if (amp!=-1)
			sp->volume=static_cast<double>(amp) / 100.0;
		else
			sp->volume=1.0;
#endif

		sp->data_length /= 2; /* These are in bytes. Convert into samples. */
		sp->loop_start /= 2;
		sp->loop_end /= 2;

		/* Then fractional samples */
		sp->data_length <<= FRACTION_BITS;
		sp->loop_start <<= FRACTION_BITS;
		sp->loop_end <<= FRACTION_BITS;

		/* Adjust for fractional loop points. This is a guess. Does anyone
		 know what "fractions" really stands for? */
		sp->loop_start |=
			(fractions & 0x0F) << (FRACTION_BITS-4);
		sp->loop_end |=
			((fractions>>4) & 0x0F) << (FRACTION_BITS-4);

		/* If this instrument will always be played on the same note,
		 and it's not looped, we can resample it now. */
		if (sp->note_to_use && !(sp->modes & MODES_LOOPING))
			pre_resample(sp);

#ifdef LOOKUP_HACK
		/* Squash the 16-bit data into 8 bits. */
		{
			uint8 *gulp,*ulp;
			sint16 *swp;
			int l=sp->data_length >> FRACTION_BITS;
			gulp=ulp=safe_Malloc<uint8>(l+1);
			swp=(sint16 *)sp->data;
			while(l--)
				*ulp++ = (*swp++ >> 8) & 0xFF;
			free(sp->data);
			sp->data=(sample_t *)gulp;
		}
#endif

		if (strip_tail==1)
		{
			/* Let's not really, just say we did. */
			ctl->cmsg(CMSG_INFO, VERB_DEBUG, " - Stripping tail");
			sp->data_length = sp->loop_end;
		}
	}

	close_file(fp);
	return ip;
}
コード例 #11
0
ファイル: sndwav_common.c プロジェクト: inn1983/soundtest
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;  
}