/** * Play sound repeatedly. * @param name sound name * @return the channel the sample is played on. On any errors, -1 is returned. */ int SDLSound::playSoundRepeatedly(const char* name) { int channel = -1; Mix_Chunk *chunk = findChunk(name); if (chunk) { if ((channel = Mix_PlayChannel(-1, chunk, -1)) == -1) { Mix_AllocateChannels(8 + Mix_AllocateChannels(-1)); if ((channel = Mix_PlayChannel(-1, chunk, -1)) == -1) { LOG (("Couldn't play sound '%s': %s", name, Mix_GetError())); } } } return channel; }
bool CubeWorld::exists( const Point& pt ) const { // sanity checkPointBounds( pt ); // Does there exist a pointer to the requested cube? OctreeChunk * chunk = findChunk( pt ); if ( chunk ) { return chunk->exists( calcRelativeChunkPoint(pt) ); } else { return false; } }
CubeData CubeWorld::get( const Point& pt ) const { checkPointBounds( pt ); // Find the chunk that holds the cube, and query the chunk for // the associated cube data. If no such cube chunk exists, then // simply return a null cube OctreeChunk * chunk = findChunk( pt ); if ( chunk == NULL ) { return CubeData::CreateNullCube(); } else { return chunk->get( calcRelativeChunkPoint( pt ) ); } }
/** * Play sound once. * @param name sound name */ void SDLSound::playSound(const char* name) { SoundData *sdata = findChunk(name); if (sdata) { if ( sdata->last_played.isTimeOut() ) { if (Mix_PlayChannel(-1, sdata->getData(), 0) == -1) { //LOG (("Couldn't play sound '%s': %s", name, Mix_GetError())); } sdata->last_played.reset(); } else { // LOGGER.debug("Skipped sound '%s' due to timeout", name); } } }
/** * Play sound once. * @param name sound name * @param distance mag2 distance */ void SDLSound::playAmbientSound(const char* name, long distance) { SoundData *sdata = findChunk(name); if (sdata) { if ( sdata->last_played.isTimeOut() ) { int oldVolume = Mix_VolumeChunk(sdata->getData(), getSoundVolume(distance)); if (Mix_PlayChannel(-1, sdata->getData(), 0) == -1) { //LOG (("Couldn't play sound '%s': %s", name, Mix_GetError())); } Mix_VolumeChunk(sdata->getData(), oldVolume); sdata->last_played.reset(); } else { // LOGGER.debug("Skipped ambient sound '%s' due to timeout", name); } } }
FILE* openWavFile(const char *filename, short *format, long *speed, int *samples, short *channels, short *width) { FILE* file; int16_t blockAlign, bitsPerSample, data16; int32_t bytesPerSec, len, data32; char tag[5]; // open file file = fopen(filename, "rb"); if (!file) return NULL; // automatically close file when we return FileCloser closer(file); // check that it's a valid sound file tag[4] = 0; if (readHeader(file, tag, &len)) return NULL; if (strcmp(tag, "RIFF") != 0) { fprintf(stderr, "File isn't a RIFF file\n"); return NULL; } if ((fread(tag, 1, 4, file) != 4) || strcmp(tag, "WAVE") != 0) { fprintf(stderr, "File isn't a proper WAVE file\n"); return NULL; } if (findChunk(file, "fmt ", &len)) { fprintf(stderr, "Couldn't find format in WAVE\n"); return NULL; } if (len < 16) { fprintf(stderr, "Chunk size not large enough\n"); return NULL; } if (readShort(file, &data16)) { fprintf(stderr, "Couldn't read format\n"); return NULL; } *format = (short)data16; if (readShort(file, &data16)) { fprintf(stderr, "Couldn't read channels\n"); return NULL; } *channels = (short)data16; if (readLong(file, &data32)) { fprintf(stderr, "Couldn't read speed\n"); return NULL; } *speed = (long)data32; if (readLong(file, &bytesPerSec)) { fprintf(stderr, "Couldn't read bytes per second\n"); return NULL; } if (readShort(file, &blockAlign)) { fprintf(stderr, "Couldn't read block alignment\n"); return NULL; } if (readShort(file, &bitsPerSample)) { fprintf(stderr, "Couldn't read bits per sample\n"); return NULL; } if (bitsPerSample==8) *width=1; else if (bitsPerSample==16) *width=2; else if (bitsPerSample==32) *width=4; else return NULL; // go find the data skipChunk(file, len - 16); if (findChunk(file, "data", &len)) { fprintf(stderr, "Failed to find the the data in WAVE\n"); return NULL; } *samples = (int)(len / (int32_t)(*width) / (int32_t)(*channels)); closer.release(); return file; }
void QWaveDecoder::handleData() { // As a special "state", if we have junk to skip, we do if (junkToSkip > 0) { discardBytes(junkToSkip); // this also updates junkToSkip // If we couldn't skip all the junk, return if (junkToSkip > 0) { // We might have run out if (source->atEnd()) parsingFailed(); return; } } if (state == QWaveDecoder::InitialState) { if (source->bytesAvailable() < qint64(sizeof(RIFFHeader))) return; RIFFHeader riff; source->read(reinterpret_cast<char *>(&riff), sizeof(RIFFHeader)); // RIFF = little endian RIFF, RIFX = big endian RIFF if (((qstrncmp(riff.descriptor.id, "RIFF", 4) != 0) && (qstrncmp(riff.descriptor.id, "RIFX", 4) != 0)) || qstrncmp(riff.type, "WAVE", 4) != 0) { parsingFailed(); return; } else { state = QWaveDecoder::WaitingForFormatState; if (qstrncmp(riff.descriptor.id, "RIFX", 4) == 0) bigEndian = true; else bigEndian = false; } } if (state == QWaveDecoder::WaitingForFormatState) { if (findChunk("fmt ")) { chunk descriptor; peekChunk(&descriptor); quint32 rawChunkSize = descriptor.size + sizeof(chunk); if (source->bytesAvailable() < qint64(rawChunkSize)) return; WAVEHeader wave; source->read(reinterpret_cast<char *>(&wave), sizeof(WAVEHeader)); if (rawChunkSize > sizeof(WAVEHeader)) discardBytes(rawChunkSize - sizeof(WAVEHeader)); // Swizzle this if (bigEndian) { wave.audioFormat = qFromBigEndian<quint16>(wave.audioFormat); } else { wave.audioFormat = qFromLittleEndian<quint16>(wave.audioFormat); } if (wave.audioFormat != 0 && wave.audioFormat != 1) { // 32bit wave files have format == 0xFFFE (WAVE_FORMAT_EXTENSIBLE). // but don't support them at the moment. parsingFailed(); return; } else { format.setCodec(QLatin1String("audio/pcm")); if (bigEndian) { int bps = qFromBigEndian<quint16>(wave.bitsPerSample); format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::BigEndian); format.setSampleRate(qFromBigEndian<quint32>(wave.sampleRate)); format.setSampleSize(bps); format.setChannelCount(qFromBigEndian<quint16>(wave.numChannels)); } else { int bps = qFromLittleEndian<quint16>(wave.bitsPerSample); format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleRate(qFromLittleEndian<quint32>(wave.sampleRate)); format.setSampleSize(bps); format.setChannelCount(qFromLittleEndian<quint16>(wave.numChannels)); } state = QWaveDecoder::WaitingForDataState; } } } if (state == QWaveDecoder::WaitingForDataState) { if (findChunk("data")) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); chunk descriptor; source->read(reinterpret_cast<char *>(&descriptor), sizeof(chunk)); if (bigEndian) descriptor.size = qFromBigEndian<quint32>(descriptor.size); else descriptor.size = qFromLittleEndian<quint32>(descriptor.size); dataSize = descriptor.size; haveFormat = true; connect(source, SIGNAL(readyRead()), SIGNAL(readyRead())); emit formatKnown(); return; } } // If we hit the end without finding data, it's a parsing error if (source->atEnd()) { parsingFailed(); } }
int32_t WavStreamer::openFile(const QString &filename) { if (m_waveStream != 0) { delete m_waveStream; m_waveStream = 0; } if (m_file.isOpen()) { m_file.close(); } m_isOK = false; // try to open the file m_file.setFileName(filename); if (m_file.open(QIODevice::ReadOnly) == false) { return -2; // error opening file } m_waveStream = new QDataStream(&m_file); // check for RIFF file & size size_t bytes = m_waveStream->readRawData(m_chunkType, 4); if ((bytes != 4) || (strncmp(m_chunkType, "RIFF", 4)!=0)) { delete m_waveStream; m_waveStream = NULL; m_file.close(); return -1; } bytes = m_waveStream->readRawData((char*)&m_chunkSize, 4); if (bytes != 4) { delete m_waveStream; m_waveStream = NULL; m_file.close(); return -1; } bytes = m_waveStream->readRawData((char*)&m_chunkType, 4); if ((bytes != 4) && (strncmp(m_chunkType, "WAVE", 4)!=0)) { delete m_waveStream; m_waveStream = NULL; m_file.close(); return -1; } m_riffSize = m_chunkSize + 8; // size of RIFF chunk + 4-byte ID + 4-byte chunksize. if (!findChunk("fmt ")) { // error, format chunk not found! delete m_waveStream; m_waveStream = NULL; m_file.close(); return -1; } // now, read the format chunk bytes = m_waveStream->readRawData((char*)&m_waveFormat, sizeof(WavFormatChunk)); if (m_waveFormat.wFormatTag == 65534) // WAVE_FORMAT_EXTENSIBLE case.. { m_waveFormat.wFormatTag = 1; // treat as PCM data, which should be the same when we have only 2 channels. } if (((m_waveFormat.wFormatTag != 3) && (m_waveFormat.wFormatTag != 1)) || (m_waveFormat.wChannels != 2)) { delete m_waveStream; m_waveStream = NULL; m_file.close(); return -1; // wrong format! } // formats smaller than 16 bits are not supported! if (m_waveFormat.wBitsPerSample < 16) { delete m_waveStream; m_waveStream = NULL; m_file.close(); return -1; } // if there are additional bytes in the format chunk, skip them. // important in the WAVE_FORMAT_EXTENSIBLE case! if (sizeof(WavFormatChunk) != m_chunkSize) { m_waveStream->skipRawData(m_chunkSize - sizeof(WavFormatChunk)); } // now, search for the audio data and set the file offset pointers if (!findChunk("data")) { delete m_waveStream; m_waveStream = NULL; m_file.close(); return -1; } m_playStart = m_waveStream->device()->pos(); m_playOffset = m_playStart; m_playEnd = m_playStart + m_chunkSize; // allocate the correct temporary buffer. if (tempBuffer!=NULL) delete[] static_cast<char*>(tempBuffer); tempBuffer = static_cast<void*>(new char[m_waveFormat.wBitsPerSample*TEMPBUFFERSIZE*2/8]); // don't forget to actually read the data readRawData(TEMPBUFFERSIZE); sampleIndex = 0; m_filename = filename; m_isOK = true; return 0; }
void QWaveDecoder::handleData() { if (state == QWaveDecoder::InitialState) { if (source->bytesAvailable() < qint64(sizeof(RIFFHeader))) return; RIFFHeader riff; source->read(reinterpret_cast<char *>(&riff), sizeof(RIFFHeader)); if (qstrncmp(riff.descriptor.id, "RIFF", 4) != 0 || qstrncmp(riff.type, "WAVE", 4) != 0) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); emit invalidFormat(); return; } else { state = QWaveDecoder::WaitingForFormatState; } } if (state == QWaveDecoder::WaitingForFormatState) { if (findChunk("fmt ")) { chunk descriptor; source->peek(reinterpret_cast<char *>(&descriptor), sizeof(chunk)); if (source->bytesAvailable() < qint64(descriptor.size + sizeof(chunk))) return; WAVEHeader wave; source->read(reinterpret_cast<char *>(&wave), sizeof(WAVEHeader)); if (descriptor.size > sizeof(WAVEHeader)) discardBytes(descriptor.size - sizeof(WAVEHeader)); if (wave.audioFormat != 0 && wave.audioFormat != 1) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); emit invalidFormat(); return; } else { int bps = qFromLittleEndian<quint16>(wave.bitsPerSample); format.setCodec(QLatin1String("audio/pcm")); format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::LittleEndian); format.setFrequency(qFromLittleEndian<quint32>(wave.sampleRate)); format.setSampleSize(bps); format.setChannels(qFromLittleEndian<quint16>(wave.numChannels)); state = QWaveDecoder::WaitingForDataState; } } } if (state == QWaveDecoder::WaitingForDataState) { if (findChunk("data")) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); chunk descriptor; source->read(reinterpret_cast<char *>(&descriptor), sizeof(chunk)); dataSize = descriptor.size; haveFormat = true; connect(source, SIGNAL(readyRead()), SIGNAL(readyRead())); emit formatKnown(); return; } } if (source->atEnd()) { source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); emit invalidFormat(); return; } }