From ac2fa3ea8db683dca17cc39bc94fc8f7122b4d65 Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Sat, 29 Jul 2006 11:43:41 +0000 Subject: fixed audio "crackling" --- muse/CMakeLists.txt | 4 +- muse/ChangeLog | 3 ++ muse/al/pos.cpp | 9 ++-- muse/muse/audio.cpp | 5 +- muse/muse/audioprefetch.cpp | 5 +- muse/muse/audiotrack.cpp | 4 +- muse/muse/midiseq.cpp | 3 +- muse/muse/plugin.cpp | 2 +- muse/muse/thread.cpp | 2 + muse/muse/wave.cpp | 103 +++++++++++++++++++++++++++++----------- muse/muse/wave.h | 10 ++-- muse/muse/waveedit/waveview.cpp | 2 +- muse/muse/waveevent.cpp | 2 +- muse/muse/wavetrack.cpp | 23 ++++++--- 14 files changed, 120 insertions(+), 57 deletions(-) diff --git a/muse/CMakeLists.txt b/muse/CMakeLists.txt index 2a254007..3a6f42b5 100644 --- a/muse/CMakeLists.txt +++ b/muse/CMakeLists.txt @@ -21,8 +21,8 @@ project(muse) CMAKE_MINIMUM_REQUIRED(VERSION 2.4.1) -# set(CMAKE_BUILD_TYPE Debug) -set(CMAKE_BUILD_TYPE Release) +set(CMAKE_BUILD_TYPE Debug) +# set(CMAKE_BUILD_TYPE Release) set(CMAKE_INCLUDE_CURRENT_DIR TRUE) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) diff --git a/muse/ChangeLog b/muse/ChangeLog index fec0424f..3523283d 100644 --- a/muse/ChangeLog +++ b/muse/ChangeLog @@ -1,3 +1,6 @@ +29.7 (ws) + * fixed drawing of waveform in wave track. Concurrent wave file + accesses from gui and rt task produced distortions ("crackling"). 25.7 (ng) DeicsOnze * add panic button 28.6. (ws) diff --git a/muse/al/pos.cpp b/muse/al/pos.cpp index 7c6e6c8e..eb3629c2 100644 --- a/muse/al/pos.cpp +++ b/muse/al/pos.cpp @@ -422,8 +422,10 @@ void PosLen::setLenTick(unsigned len) { _lenTick = len; sn = -1; -// if (type() == FRAMES) + if (type() == FRAMES) _lenFrame = tempomap.tick2frame(len, &sn); + else + _lenTick = len; } //--------------------------------------------------------- @@ -432,10 +434,11 @@ void PosLen::setLenTick(unsigned len) void PosLen::setLenFrame(unsigned len) { - _lenFrame = len; sn = -1; -// if (type() == TICKS) + if (type() == TICKS) _lenTick = tempomap.frame2tick(len, &sn); + else + _lenFrame = len; } //--------------------------------------------------------- diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp index 42cd3255..f27cf6fd 100644 --- a/muse/muse/audio.cpp +++ b/muse/muse/audio.cpp @@ -307,7 +307,7 @@ void Audio::process(unsigned frames) ++watchAudio; // make a simple watchdog happy if (msg) { -// printf("msg\n"); +// printf("---msg\n"); processMsg(msg); int sn = msg->serialNo; msg = 0; // dont process again @@ -363,7 +363,6 @@ void Audio::process(unsigned frames) (*i)->silence(frames); return; } - unsigned framePos = _pos.frame(); if (state == PLAY) { @@ -552,7 +551,7 @@ void Audio::process(unsigned frames) void Audio::processMsg(AudioMsg* msg) { // if (_running) -// printf("audio process %d\n", msg->id); + printf("audio process %d\n", msg->id); switch(msg->id) { case AUDIO_ROUTEADD: diff --git a/muse/muse/audioprefetch.cpp b/muse/muse/audioprefetch.cpp index f9853f6a..7f6711f7 100644 --- a/muse/muse/audioprefetch.cpp +++ b/muse/muse/audioprefetch.cpp @@ -111,9 +111,9 @@ void AudioPrefetch::processMsg1(const void* m) void AudioPrefetch::msgTick() { - PrefetchMsg msg; - msg.id = PREFETCH_TICK; if (fifo.count() < FIFO_BUFFER/3) { + PrefetchMsg msg; + msg.id = PREFETCH_TICK; while (sendMsg1(&msg, sizeof(msg))) { printf("AudioPrefetch::msgTick(): send failed!\n"); } @@ -174,7 +174,6 @@ void AudioPrefetch::prefetch(bool seekFlag) WaveTrack* track = *it; if (!seekFlag && ((audio->isRecording() && track->recordFlag()) || !audio->isPlaying())) continue; - // int ch = track->channels(); track->fetchData(writePos, segmentSize, widx); } writePos += segmentSize; diff --git a/muse/muse/audiotrack.cpp b/muse/muse/audiotrack.cpp index 0d99a746..02cd857a 100644 --- a/muse/muse/audiotrack.cpp +++ b/muse/muse/audiotrack.cpp @@ -503,8 +503,8 @@ bool AudioTrack::multiplyCopy(int dstChannels, float** dstBuffer, int ctrl) if (_mute || bufferEmpty || _volume == 0.0) return false; int srcChannels = channels(); - double vol[2]; - double _pan = ctrlVal(AC_PAN).f; + float vol[2]; + float _pan = ctrlVal(AC_PAN).f; vol[0] = _volume * (1.0 - _pan); vol[1] = _volume * (1.0 + _pan); diff --git a/muse/muse/midiseq.cpp b/muse/muse/midiseq.cpp index d1bcc114..0895096b 100644 --- a/muse/muse/midiseq.cpp +++ b/muse/muse/midiseq.cpp @@ -60,6 +60,7 @@ static void readMsg(void* p, void*) void MidiSeq::processMsg(const ThreadMsg* m) { + AudioMsg* msg = (AudioMsg*)m; switch (msg->id) { case MS_PROCESS: @@ -397,12 +398,12 @@ void MidiSeq::updatePollFd() if (!isRunning()) return; clearPollFd(); + if (timer) { int timerFd = timer->getFd(); if (timerFd != -1) addPollFd(timerFd, POLLIN, midiTick, this, 0); } - addPollFd(toThreadFdr, POLLIN, ::readMsg, this, 0); struct pollfd* pfd; diff --git a/muse/muse/plugin.cpp b/muse/muse/plugin.cpp index c5d6362a..aeee6cc5 100644 --- a/muse/muse/plugin.cpp +++ b/muse/muse/plugin.cpp @@ -231,7 +231,7 @@ Plugin* PluginList::find(const QString& file, const QString& name) if ((file == (*i)->lib()) && (name == (*i)->label())) return *i; } - printf("Plugin <%s> not found\n", name.toLatin1().data()); + printf("MusE: Plugin <%s> not found\n", name.toAscii().data()); return 0; } diff --git a/muse/muse/thread.cpp b/muse/muse/thread.cpp index c77d8ab9..ea8de818 100644 --- a/muse/muse/thread.cpp +++ b/muse/muse/thread.cpp @@ -231,6 +231,8 @@ void Thread::loop() while (_running) { if (debugMode) // DEBUG _pollWait = 10; // ms + else + _pollWait = -1; int n = poll(pfd, npfd, _pollWait); if (n < 0) { diff --git a/muse/muse/wave.cpp b/muse/muse/wave.cpp index 9b6fc1d2..9b40c967 100644 --- a/muse/muse/wave.cpp +++ b/muse/muse/wave.cpp @@ -253,7 +253,8 @@ SndFile::SndFile(const QString& name) { refCount = 0; _finfo.setFile(name); - sf = 0; + sfRT = 0; + sfUI = 0; csize = 0; cache = 0; openFlag = false; @@ -284,8 +285,11 @@ bool SndFile::openRead() return false; } QString p = _finfo.absoluteFilePath(); - sf = sf_open(p.toLatin1().data(), SFM_READ, &sfinfo); - if (sf == 0) + sfinfo.format = 0; + sfUI = sf_open(p.toAscii().data(), SFM_READ, &sfinfo); + sfinfo.format = 0; + sfRT = sf_open(p.toAscii().data(), SFM_READ, &sfinfo); + if (sfUI == 0 || sfRT == 0) return true; writeFlag = false; openFlag = true; @@ -335,7 +339,7 @@ void SndFile::readCache(const QString& path, bool showProgress) for (unsigned ch = 0; ch < channels(); ++ch) cache[ch] = new SampleV[csize]; - FILE* cfile = fopen(path.toLatin1().data(), "r"); + FILE* cfile = fopen(path.toAscii().data(), "r"); if (cfile) { for (unsigned ch = 0; ch < channels(); ++ch) fread(cache[ch], csize * sizeof(SampleV), 1, cfile); @@ -368,7 +372,7 @@ void SndFile::readCache(const QString& path, bool showProgress) // TODO } } - seek(i * cacheMag, 0); + seek(i * cacheMag); read(channels(), fp, cacheMag); for (unsigned ch = 0; ch < channels(); ++ch) { float rms = 0.0; @@ -426,18 +430,44 @@ void SndFile::read(SampleV* s, int mag, unsigned pos) s[ch].peak = 0; s[ch].rms = 0; } - if (pos > samples()) { -// printf("%p pos %d > samples %d\n", this, pos, samples()); + if (pos > samples()) return; - } if (mag < cacheMag) { float data[channels()][mag]; float* fp[channels()]; for (unsigned i = 0; i < channels(); ++i) fp[i] = &data[i][0]; - seek(pos, 0); - read(channels(), fp, mag); + sf_seek(sfUI, pos, SEEK_SET); + { + int srcChannels = channels(); + int dstChannels = sfinfo.channels; + size_t n = mag; + float** dst = fp; + float buffer[n * dstChannels]; + size_t rn = sf_readf_float(sfUI, buffer, n); + float* src = buffer; + + if (srcChannels == dstChannels) { + for (size_t i = 0; i < rn; ++i) { + for (int ch = 0; ch < srcChannels; ++ch) + *(dst[ch]+i) = *src++; + } + } + else if ((srcChannels == 1) && (dstChannels == 2)) { + // stereo to mono + for (size_t i = 0; i < rn; ++i) + *(dst[0] + i) = src[i + i] + src[i + i + 1]; + } + else if ((srcChannels == 2) && (dstChannels == 1)) { + // mono to stereo + for (size_t i = 0; i < rn; ++i) { + float data = *src++; + *(dst[0]+i) = data; + *(dst[1]+i) = data; + } + } + } for (unsigned ch = 0; ch < channels(); ++ch) { s[ch].peak = 0; @@ -459,7 +489,7 @@ void SndFile::read(SampleV* s, int mag, unsigned pos) int rest = csize - (pos/cacheMag); int end = mag; if (rest < mag) - end = rest; + end = rest; for (unsigned ch = 0; ch < channels(); ++ch) { int rms = 0; @@ -485,15 +515,16 @@ bool SndFile::openWrite() return false; } QString p = _finfo.filePath(); - sf = sf_open(p.toLatin1().data(), SFM_RDWR, &sfinfo); - if (sf) { + sfRT = sf_open(p.toLatin1().data(), SFM_RDWR, &sfinfo); + sfUI = 0; + if (sfRT) { openFlag = true; writeFlag = true; QString cacheName = _finfo.absolutePath() + QString("/") + _finfo.baseName() + QString(".wca"); readCache(cacheName, true); } - return sf == 0; + return sfRT == 0; } //--------------------------------------------------------- @@ -506,7 +537,9 @@ void SndFile::close() printf("SndFile:: alread closed\n"); return; } - sf_close(sf); + sf_close(sfRT); + if (sfUI) + sf_close(sfUI); openFlag = false; } @@ -521,9 +554,9 @@ void SndFile::remove() QString cacheName = _finfo.absolutePath() + QString("/") + _finfo.baseName() + QString(".wca"); // QFile::remove(_finfo.filePath()); // QFile::remove(cacheName); + // DEBUG: QFile::rename(_finfo.filePath(), _finfo.filePath() + ".del"); QFile::rename(cacheName, cacheName + ".del"); - } //--------------------------------------------------------- @@ -532,10 +565,7 @@ void SndFile::remove() unsigned SndFile::samples() const { - sf_count_t curPos = sf_seek(sf, 0, SEEK_CUR); - int frames = sf_seek(sf, 0, SEEK_END); - sf_seek(sf, curPos, SEEK_SET); - return frames; + return sfinfo.frames; } //--------------------------------------------------------- @@ -547,16 +577,28 @@ unsigned SndFile::channels() const return sfinfo.channels; } +//--------------------------------------------------------- +// samplerate +//--------------------------------------------------------- + unsigned SndFile::samplerate() const { return sfinfo.samplerate; } +//--------------------------------------------------------- +// format +//--------------------------------------------------------- + unsigned SndFile::format() const { return sfinfo.format; } +//--------------------------------------------------------- +// setFormat +//--------------------------------------------------------- + void SndFile::setFormat(int fmt, int ch, int rate) { sfinfo.samplerate = rate; @@ -573,7 +615,9 @@ void SndFile::setFormat(int fmt, int ch, int rate) size_t SndFile::read(int srcChannels, float** dst, size_t n) { float buffer[n * sfinfo.channels]; - size_t rn = sf_readf_float(sf, buffer, n); + size_t rn = sf_readf_float(sfRT, buffer, n); +// sf_seek(sfRT, n, SEEK_CUR); //libsndfile does not update position?? + float* src = buffer; int dstChannels = sfinfo.channels; @@ -637,16 +681,16 @@ size_t SndFile::write(int srcChannels, float** src, size_t n) srcChannels, dstChannels); return 0; } - return sf_writef_float(sf, buffer, n) ; + return sf_writef_float(sfRT, buffer, n) ; } //--------------------------------------------------------- // seek //--------------------------------------------------------- -off_t SndFile::seek(off_t frames, int whence) +off_t SndFile::seek(off_t frames) { - return sf_seek(sf, frames, whence); + return sf_seek(sfRT, frames, SEEK_SET); } //--------------------------------------------------------- @@ -657,7 +701,7 @@ QString SndFile::strerror() const { char buffer[128]; buffer[0] = 0; - sf_error_str(sf, buffer, 128); + sf_error_str(sfRT, buffer, 128); return QString(buffer); } @@ -705,6 +749,7 @@ SndFile* SndFile::getWave(const QString& inName, bool writeFlag) //--------------------------------------------------------- // applyUndoFile //--------------------------------------------------------- + void SndFile::applyUndoFile(const QString& original, const QString& tmpfile, unsigned startframe, unsigned endframe) { // This one is called on both undo and redo of a wavfile @@ -750,7 +795,7 @@ void SndFile::applyUndoFile(const QString& original, const QString& tmpfile, uns for (unsigned i=0; iseek(startframe, 0); + orig->seek(startframe); orig->read(file_channels, data2beoverwritten, tmpdatalen); orig->close(); @@ -760,7 +805,7 @@ void SndFile::applyUndoFile(const QString& original, const QString& tmpfile, uns for (unsigned i=0; iseek(startframe, 0); + orig->seek(startframe); orig->write(file_channels, tmpfiledata, tmpdatalen); // Delete dataholder for temporary file @@ -784,7 +829,7 @@ void SndFile::applyUndoFile(const QString& original, const QString& tmpfile, uns audio->msgIdle(false); return; } - tmp.seek(0, 0); + tmp.seek(0); tmp.write(file_channels, data2beoverwritten, tmpdatalen); tmp.close(); diff --git a/muse/muse/wave.h b/muse/muse/wave.h index 0db8c27c..42054f87 100644 --- a/muse/muse/wave.h +++ b/muse/muse/wave.h @@ -48,8 +48,10 @@ class SndFile { static QHash sndFiles; static QList createdFiles; static int recFileNumber; + QFileInfo _finfo; - SNDFILE* sf; + SNDFILE* sfRT; // used by rt process (prefetch) + SNDFILE* sfUI; // used by ui process SF_INFO sfinfo; SampleV** cache; int csize; // frames in cache @@ -90,7 +92,7 @@ class SndFile { size_t read(int channel, float**, size_t); size_t write(int channel, float**, size_t); - off_t seek(off_t frames, int whence); + off_t seek(off_t frames); void read(SampleV* s, int mag, unsigned pos); QString strerror() const; @@ -147,8 +149,8 @@ class SndFileR { size_t write(int channel, float** f, size_t n) { return sf->write(channel, f, n); } - off_t seek(off_t frames, int whence) { - return sf->seek(frames, whence); + off_t seek(off_t frames) { + return sf->seek(frames); } void read(SampleV* s, int mag, unsigned pos) { sf->read(s, mag, pos); diff --git a/muse/muse/waveedit/waveview.cpp b/muse/muse/waveedit/waveview.cpp index 38d9f052..f1352f6d 100644 --- a/muse/muse/waveedit/waveview.cpp +++ b/muse/muse/waveedit/waveview.cpp @@ -729,7 +729,7 @@ void WaveView::editExternal(unsigned file_format, unsigned file_samplerate, unsi } else { // Re-read file again - exttmpFile.seek(0, 0); + exttmpFile.seek(0); size_t sz = exttmpFile.read(file_channels, tmpdata, tmpdatalen); if (sz != tmpdatalen) { // File must have been shrunken - not good. Alert user. diff --git a/muse/muse/waveevent.cpp b/muse/muse/waveevent.cpp index 2d54cc99..82d451ae 100644 --- a/muse/muse/waveevent.cpp +++ b/muse/muse/waveevent.cpp @@ -115,7 +115,7 @@ void WaveEventBase::read(unsigned offset, float** buffer, int channel, int n) { if (f.isNull()) return; - f.seek(offset + _spos, 0); + f.seek(offset + _spos); f.read(channel, buffer, n); } diff --git a/muse/muse/wavetrack.cpp b/muse/muse/wavetrack.cpp index 10753640..7aa299fc 100644 --- a/muse/muse/wavetrack.cpp +++ b/muse/muse/wavetrack.cpp @@ -77,10 +77,16 @@ void WaveTrack::fetchData(unsigned pos, unsigned samples, int widx) float** bp = readBuffer[widx]; for (int i = 0; i < channels(); ++i) memset(bp[i], 0, samples * sizeof(float)); - PartList* pl = parts(); + PartList* pl = parts(); for (iPart ip = pl->begin(); ip != pl->end(); ++ip) { Part* part = ip->second; + + // DEBUG + int type = int(part->type()); + if (type != AL::FRAMES) + printf("part has wrong type\n"); + if (part->mute()) continue; unsigned p_spos = part->frame(); @@ -117,11 +123,14 @@ void WaveTrack::fetchData(unsigned pos, unsigned samples, int widx) if (nn > samples) nn = samples; } - float* bpp[channels()]; - for (int i = 0; i < channels(); ++i) - bpp[i] = bp[i] + dstOffset; - - event.read(srcOffset, bpp, channels(), nn); + if (dstOffset) { + float* bpp[channels()]; + for (int i = 0; i < channels(); ++i) + bpp[i] = bp[i] + dstOffset; + event.read(srcOffset, bpp, channels(), nn); + } + else + event.read(srcOffset, bp, channels(), nn); } } } @@ -381,7 +390,7 @@ void WaveTrack::process() void WaveTrack::clone(WaveTrack* t) { -printf("cline WaveTrack\n"); +printf("clone WaveTrack\n"); QString name; for (int i = 1; ; ++i) { name.sprintf("%s-%d", t->name().toLatin1().data(), i); -- cgit v1.2.3