/[svn]/linuxsampler/tags/start/audiothread.cpp
ViewVC logotype

Contents of /linuxsampler/tags/start/audiothread.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (show annotations) (download)
Sat Oct 25 20:24:32 2003 UTC (20 years, 5 months ago) by (unknown author)
File size: 7554 byte(s)
This commit was manufactured by cvs2svn to create tag 'start'.
1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "audiothread.h"
24
25 AudioThread::AudioThread(AudioIO* pAudioIO, DiskThread* pDiskThread, gig::Instrument* pInstrument) : Thread(true, 1, 0) {
26 this->pAudioIO = pAudioIO;
27 this->pDiskThread = pDiskThread;
28 this->pInstrument = pInstrument;
29 pCommandQueue = new RingBuffer<command_t>(1024);
30 pVoices = new Voice*[MAX_AUDIO_VOICES];
31 for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
32 pVoices[i] = new Voice(pDiskThread);
33 }
34 for (uint i = 0; i < 128; i++) {
35 ActiveVoices[i] = NULL;
36 }
37
38 pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];
39
40 // set all voice outputs to the AudioSumBuffer
41 for (int i = 0; i < MAX_AUDIO_VOICES; i++) {
42 pVoices[i]->SetOutput(pAudioSumBuffer, pAudioIO->FragmentSize * 2); //FIXME: assuming stereo
43 }
44
45 // cache initial samples points (for actually needed samples)
46 dmsg(("Caching initial samples..."));
47 gig::Region* pRgn = this->pInstrument->GetFirstRegion();
48 while (pRgn) {
49 if (!pRgn->GetSample()->GetCache().Size) {
50 CacheInitialSamples(pRgn->GetSample());
51 }
52 for (uint i = 0; i < pRgn->DimensionRegions; i++) {
53 CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample);
54 }
55
56 pRgn = this->pInstrument->GetNextRegion();
57 }
58 dmsg(("OK\n"));
59 }
60
61 AudioThread::~AudioThread() {
62 if (pCommandQueue) delete pCommandQueue;
63 if (pVoices) {
64 for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
65 if (pVoices[i]) delete pVoices[i];
66 }
67 }
68 delete[] pVoices;
69 }
70
71 int AudioThread::Main() {
72 dmsg(("Audio thread running\n"));
73
74 while (true) {
75
76 // read and process commands from the queue
77 while (true) {
78 command_t command;
79 if (pCommandQueue->read(&command, 1) == 0) break;
80
81 switch (command.type) {
82 case command_type_note_on:
83 dmsg(("Audio Thread: Note on received\n"));
84 ActivateVoice(command.pitch, command.velocity);
85 break;
86 case command_type_note_off:
87 dmsg(("Audio Thread: Note off received\n"));
88 ReleaseVoice(command.pitch, command.velocity);
89 break;
90 }
91 }
92
93
94 // zero out the sum buffer
95 for (uint u = 0; u < pAudioIO->FragmentSize * pAudioIO->Channels; u++) {
96 pAudioSumBuffer[u] = 0.0;
97 }
98
99
100 // render audio from all active voices
101 for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
102 if (pVoices[i]->IsActive()) {
103 pVoices[i]->RenderAudio();
104 }
105 }
106
107
108 // check clipping in the audio sum, convert to sample_type
109 // (from 32bit to 16bit sample) and copy to output buffer
110 float sample_point;
111 for (uint u = 0; u < pAudioIO->FragmentSize * pAudioIO->Channels; u++) {
112 sample_point = this->pAudioSumBuffer[u] / 4; // FIXME division by 4 just for testing purposes (to give a bit of head room when mixing multiple voices together)
113 if (sample_point < -32768.0) sample_point = -32768.0;
114 if (sample_point > 32767.0) sample_point = 32767.0;
115 this->pAudioIO->pOutputBuffer[u] = (sample_t) sample_point;
116 }
117
118
119 // call audio driver to output sound
120 int res = this->pAudioIO->Output();
121 if (res < 0) exit(EXIT_FAILURE);
122 }
123 }
124
125 /// Will be called by the MIDIIn Thread to let the audio thread trigger a new voice.
126 void AudioThread::ProcessNoteOn(uint8_t Pitch, uint8_t Velocity) {
127 command_t cmd;
128 cmd.type = command_type_note_on;
129 cmd.pitch = Pitch;
130 cmd.velocity = Velocity;
131 this->pCommandQueue->write(&cmd, 1);
132 }
133
134 /// Will be called by the MIDIIn Thread to signal the audio thread to release a voice.
135 void AudioThread::ProcessNoteOff(uint8_t Pitch, uint8_t Velocity) {
136 command_t cmd;
137 cmd.type = command_type_note_off;
138 cmd.pitch = Pitch;
139 cmd.velocity = Velocity;
140 this->pCommandQueue->write(&cmd, 1);
141 }
142
143 void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {
144 for (int i = 0; i < MAX_AUDIO_VOICES; i++) {
145 if (pVoices[i]->IsActive()) continue;
146 pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);
147 ActiveVoices[MIDIKey] = pVoices[i];
148 return;
149 }
150 std::cerr << "No free voice!" << std::endl << std::flush;
151 }
152
153 void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {
154 Voice* pVoice = ActiveVoices[MIDIKey];
155 if (pVoice) {
156 pVoice->Kill(); //TODO: for now we're rude and just kill the poor, poor voice immediately :), later we add a Release() method to the Voice class and call it here to let the voice go through it's release phase
157 ActiveVoices[MIDIKey] = NULL;
158 }
159 else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush;
160 }
161
162 void AudioThread::CacheInitialSamples(gig::Sample* pSample) {
163 if (!pSample || pSample->GetCache().Size) return;
164 if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {
165 // Sample is too short for disk streaming, so we load the whole
166 // sample into RAM and place 'pAudioIO->FragmentSize << MAX_PITCH'
167 // number of '0' samples (silence samples) behind the official buffer
168 // border, to allow the interpolator do it's work even at the end of
169 // the sample.
170 gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(pAudioIO->FragmentSize << MAX_PITCH);
171 dmsg(("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
172 }
173 else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk
174 pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);
175 }
176
177 if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
178 }

  ViewVC Help
Powered by ViewVC