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