/[svn]/linuxsampler/trunk/src/stream.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/stream.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations) (download)
Fri Dec 26 16:39:58 2003 UTC (20 years, 4 months ago) by schoenebeck
File size: 5393 byte(s)
* implemented looping; RAM only loops (that is loops that end within the
  cached part of the sample) are handled in src/voice.cpp whereas
  disk stream looping is handled in src/stream.cpp and is mostly covered
  there by the new ReadAndLoop() method in class 'Sample' from src/gig.cpp

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 by Benno Senoner *
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 "stream.h"
24
25 // FIXME: already independent of audio channels, but assumes sample depth defined by 'sample_t' (usually 16 bit)
26
27
28 // *********** Stream **************
29 // *
30
31 uint Stream::UnusedStreams = 0;
32
33 /// Returns number of refilled sample points or a value < 0 on error.
34 int Stream::ReadAhead(unsigned long SampleCount) {
35 if (this->State == state_unused) return -1;
36 if (this->State == state_end) return 0;
37 if (!SampleCount) return 0;
38 if (!pRingBuffer->write_space()) return 0;
39
40 long total_readsamples = 0, readsamples = 0;
41 long samplestoread = SampleCount / pSample->Channels;
42 sample_t* pBuf = pRingBuffer->get_write_ptr();
43 bool endofsamplereached;
44
45 // refill the disk stream buffer
46 if (this->DoLoop) { // honor looping
47 total_readsamples = pSample->ReadAndLoop(pBuf, samplestoread, &this->PlaybackState);
48 endofsamplereached = (this->PlaybackState.position >= pSample->SamplesTotal);
49 dmsg(5,("Refilled stream %d with %d (SamplePos: %d)", this->hThis, total_readsamples, this->PlaybackState.position));
50 }
51 else { // normal forward playback
52
53 pSample->SetPos(this->SampleOffset); // recover old position
54
55 do {
56 readsamples = pSample->Read(&pBuf[total_readsamples * pSample->Channels], samplestoread);
57 samplestoread -= readsamples;
58 total_readsamples += readsamples;
59 } while (samplestoread && readsamples > 0);
60
61 // we have to store the position within the sample, because other streams might use the same sample
62 this->SampleOffset = pSample->GetPos();
63
64 endofsamplereached = (SampleOffset >= pSample->SamplesTotal);
65 dmsg(5,("Refilled stream %d with %d (SamplePos: %d)", this->hThis, total_readsamples, this->SampleOffset));
66 }
67
68 // we must delay the increment_write_ptr_with_wrap() after the while() loop because we need to
69 // ensure that we read exactly SampleCount sample, otherwise the buffer wrapping code will fail
70 pRingBuffer->increment_write_ptr_with_wrap(total_readsamples * pSample->Channels);
71
72 // update stream state
73 if (endofsamplereached) SetState(state_end);
74 else SetState(state_active);
75
76 return total_readsamples;
77 }
78
79 void Stream::WriteSilence(unsigned long SilenceSampleWords) {
80 memset(pRingBuffer->get_write_ptr(), 0, SilenceSampleWords);
81 pRingBuffer->increment_write_ptr_with_wrap(SilenceSampleWords);
82 }
83
84 Stream::Stream(uint BufferSize, uint BufferWrapElements) {
85 this->pExportReference = NULL;
86 this->State = state_unused;
87 this->hThis = 0;
88 this->pSample = NULL;
89 this->SampleOffset = 0;
90 this->PlaybackState.position = 0;
91 this->PlaybackState.reverse = false;
92 this->pRingBuffer = new RingBuffer<sample_t>(BufferSize, BufferWrapElements);
93 UnusedStreams++;
94 }
95
96 Stream::~Stream() {
97 Reset();
98 if (pRingBuffer) delete pRingBuffer;
99 }
100
101 /// Called by disk thread to activate the disk stream.
102 void Stream::Launch(Stream::Handle hStream, reference_t* pExportReference, gig::Sample* pSample, unsigned long SampleOffset, bool DoLoop) {
103 UnusedStreams--;
104 this->pExportReference = pExportReference;
105 this->hThis = hStream;
106 this->pSample = pSample;
107 this->SampleOffset = SampleOffset;
108 this->PlaybackState.position = SampleOffset;
109 this->PlaybackState.reverse = false;
110 this->PlaybackState.loop_cycles_left = pSample->LoopPlayCount;
111 this->DoLoop = DoLoop;
112 SetState(state_active);
113 }

  ViewVC Help
Powered by ViewVC