Mercurial > hg > svapp
comparison audioio/AudioCallbackPlaySource.cpp @ 7:3a41ba527b4a
* Add command history class, and basic undo/redo menus. No actual commands
to undo/redo yet. Selecting the placeholders sometimes seems to cause
a crash, so this looks a little uncertain so far.
* Add Rename Layer
* Remove models from playback when their layers are removed (and ref counts
hit zero)
* Don't hang around waiting so much when there's work to be done in the audio
buffer fill thread
* Put more sensible names on layers generated from transforms
* Add basic editing to time-value layer like existing editing in time-instants
layer, and make both of them snap to the appropriate resolution during drag
author | Chris Cannam |
---|---|
date | Mon, 30 Jan 2006 17:51:56 +0000 |
parents | f3d777b693f7 |
children | 24b500216029 |
comparison
equal
deleted
inserted
replaced
6:f3d777b693f7 | 7:3a41ba527b4a |
---|---|
620 size_t request = count; | 620 size_t request = count; |
621 if (ch > 0) request = got; | 621 if (ch > 0) request = got; |
622 | 622 |
623 got = rb->read(buffer[ch], request); | 623 got = rb->read(buffer[ch], request); |
624 | 624 |
625 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 625 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING |
626 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", signalling for more (possibly)" << std::endl; | 626 std::cout << "AudioCallbackPlaySource::getSamples: got " << got << " samples on channel " << ch << ", signalling for more (possibly)" << std::endl; |
627 #endif | 627 #endif |
628 } | 628 } |
629 | 629 |
630 for (size_t ch = 0; ch < getSourceChannelCount(); ++ch) { | 630 for (size_t ch = 0; ch < getSourceChannelCount(); ++ch) { |
682 for (size_t i = 0; i < count; ++i) { | 682 for (size_t i = 0; i < count; ++i) { |
683 buffer[ch][i] = ob[m_slowdownCounter * count + i]; | 683 buffer[ch][i] = ob[m_slowdownCounter * count + i]; |
684 } | 684 } |
685 } | 685 } |
686 | 686 |
687 if (m_slowdownCounter == 0) m_condition.wakeAll(); | 687 //!!! if (m_slowdownCounter == 0) m_condition.wakeAll(); |
688 m_slowdownCounter = (m_slowdownCounter + 1) % timeStretcher->getFactor(); | 688 m_slowdownCounter = (m_slowdownCounter + 1) % timeStretcher->getFactor(); |
689 return count; | 689 return count; |
690 } | 690 } |
691 | 691 |
692 // Called from fill thread, m_playing true, mutex held | 692 // Called from fill thread, m_playing true, mutex held |
693 void | 693 bool |
694 AudioCallbackPlaySource::fillBuffers() | 694 AudioCallbackPlaySource::fillBuffers() |
695 { | 695 { |
696 static float *tmp = 0; | 696 static float *tmp = 0; |
697 static size_t tmpSize = 0; | 697 static size_t tmpSize = 0; |
698 | 698 |
703 size_t spaceHere = wb->getWriteSpace(); | 703 size_t spaceHere = wb->getWriteSpace(); |
704 if (c == 0 || spaceHere < space) space = spaceHere; | 704 if (c == 0 || spaceHere < space) space = spaceHere; |
705 } | 705 } |
706 } | 706 } |
707 | 707 |
708 if (space == 0) return; | 708 if (space == 0) return false; |
709 | 709 |
710 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 710 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
711 std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl; | 711 std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl; |
712 #endif | 712 #endif |
713 | 713 |
752 double(getTargetSampleRate()) / double(getSourceSampleRate()); | 752 double(getTargetSampleRate()) / double(getSourceSampleRate()); |
753 orig = size_t(orig / ratio + 0.1); | 753 orig = size_t(orig / ratio + 0.1); |
754 | 754 |
755 // orig must be a multiple of generatorBlockSize | 755 // orig must be a multiple of generatorBlockSize |
756 orig = (orig / generatorBlockSize) * generatorBlockSize; | 756 orig = (orig / generatorBlockSize) * generatorBlockSize; |
757 if (orig == 0) return; | 757 if (orig == 0) return false; |
758 | 758 |
759 size_t work = std::max(orig, space); | 759 size_t work = std::max(orig, space); |
760 | 760 |
761 // We only allocate one buffer, but we use it in two halves. | 761 // We only allocate one buffer, but we use it in two halves. |
762 // We place the non-interleaved values in the second half of | 762 // We place the non-interleaved values in the second half of |
836 | 836 |
837 } else { | 837 } else { |
838 | 838 |
839 // space must be a multiple of generatorBlockSize | 839 // space must be a multiple of generatorBlockSize |
840 space = (space / generatorBlockSize) * generatorBlockSize; | 840 space = (space / generatorBlockSize) * generatorBlockSize; |
841 if (space == 0) return; | 841 if (space == 0) return false; |
842 | 842 |
843 if (tmpSize < channels * space) { | 843 if (tmpSize < channels * space) { |
844 delete[] tmp; | 844 delete[] tmp; |
845 tmp = new float[channels * space]; | 845 tmp = new float[channels * space]; |
846 tmpSize = channels * space; | 846 tmpSize = channels * space; |
871 } | 871 } |
872 | 872 |
873 m_bufferedToFrame = f; | 873 m_bufferedToFrame = f; |
874 //!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples | 874 //!!! how do we know when ended? need to mark up a fully-buffered flag and check this if we find the buffers empty in getSourceSamples |
875 } | 875 } |
876 | |
877 return true; | |
876 } | 878 } |
877 | 879 |
878 size_t | 880 size_t |
879 AudioCallbackPlaySource::mixModels(size_t &frame, size_t count, float **buffers) | 881 AudioCallbackPlaySource::mixModels(size_t &frame, size_t count, float **buffers) |
880 { | 882 { |
1018 processed += chunkSize; | 1020 processed += chunkSize; |
1019 chunkStart = nextChunkStart; | 1021 chunkStart = nextChunkStart; |
1020 } | 1022 } |
1021 | 1023 |
1022 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 1024 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
1023 std::cerr << "Returning selection playback at " << nextChunkStart << std::endl; | 1025 std::cerr << "Returning selection playback " << processed << " frames to " << nextChunkStart << std::endl; |
1024 #endif | 1026 #endif |
1025 | 1027 |
1026 frame = nextChunkStart; | 1028 frame = nextChunkStart; |
1027 return processed; | 1029 return processed; |
1028 } | 1030 } |
1037 #endif | 1039 #endif |
1038 | 1040 |
1039 s.m_mutex.lock(); | 1041 s.m_mutex.lock(); |
1040 | 1042 |
1041 bool previouslyPlaying = s.m_playing; | 1043 bool previouslyPlaying = s.m_playing; |
1044 bool work = false; | |
1042 | 1045 |
1043 while (!s.m_exiting) { | 1046 while (!s.m_exiting) { |
1044 | 1047 |
1045 if (s.m_readBuffers != s.m_writeBuffers) { | 1048 if (s.m_readBuffers != s.m_writeBuffers) { |
1046 s.m_bufferScavenger.claim(s.m_readBuffers); | 1049 s.m_bufferScavenger.claim(s.m_readBuffers); |
1047 s.m_readBuffers = s.m_writeBuffers; | 1050 s.m_readBuffers = s.m_writeBuffers; |
1048 std::cerr << "unified" << std::endl; | 1051 std::cerr << "unified" << std::endl; |
1049 } | 1052 } |
1050 | 1053 |
1051 s.m_bufferScavenger.scavenge(); | 1054 s.m_bufferScavenger.scavenge(); |
1052 | |
1053 s.m_timeStretcherScavenger.scavenge(); | 1055 s.m_timeStretcherScavenger.scavenge(); |
1054 | 1056 |
1055 float ms = 100; | 1057 if (work && s.m_playing && s.getSourceSampleRate()) { |
1056 if (s.getSourceSampleRate() > 0) { | 1058 |
1057 ms = float(m_ringBufferSize) / float(s.getSourceSampleRate()) * 1000.0; | 1059 s.m_mutex.unlock(); |
1058 } | 1060 s.m_mutex.lock(); |
1059 | 1061 |
1060 if (!s.m_playing) ms *= 10; | 1062 } else { |
1061 ms = ms / 8; | 1063 |
1062 | 1064 float ms = 100; |
1063 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 1065 if (s.getSourceSampleRate() > 0) { |
1064 std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl; | 1066 ms = float(m_ringBufferSize) / float(s.getSourceSampleRate()) * 1000.0; |
1065 #endif | 1067 } |
1066 | 1068 |
1067 s.m_condition.wait(&s.m_mutex, size_t(ms)); | 1069 if (s.m_playing) ms /= 10; |
1070 | |
1071 #ifdef DEBUG_AUDIO_PLAY_SOURCE | |
1072 std::cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << std::endl; | |
1073 #endif | |
1074 | |
1075 s.m_condition.wait(&s.m_mutex, size_t(ms)); | |
1076 } | |
1068 | 1077 |
1069 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 1078 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
1070 std::cout << "AudioCallbackPlaySourceFillThread: awoken" << std::endl; | 1079 std::cout << "AudioCallbackPlaySourceFillThread: awoken" << std::endl; |
1071 #endif | 1080 #endif |
1081 | |
1082 work = false; | |
1072 | 1083 |
1073 if (!s.getSourceSampleRate()) continue; | 1084 if (!s.getSourceSampleRate()) continue; |
1074 | 1085 |
1075 bool playing = s.m_playing; | 1086 bool playing = s.m_playing; |
1076 | 1087 |
1083 if (rb) rb->reset(); | 1094 if (rb) rb->reset(); |
1084 } | 1095 } |
1085 } | 1096 } |
1086 previouslyPlaying = playing; | 1097 previouslyPlaying = playing; |
1087 | 1098 |
1088 s.fillBuffers(); | 1099 work = s.fillBuffers(); |
1089 } | 1100 } |
1090 | 1101 |
1091 s.m_mutex.unlock(); | 1102 s.m_mutex.unlock(); |
1092 } | 1103 } |
1093 | 1104 |