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; }
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; }
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; }
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; }
// 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; }
/* 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); } }
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; }
/* 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; }
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, ¬e, &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; }
/* 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; }
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; }