libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / apps / soundrecorder / VUView.cpp
blob2f6112be63bcb6dbbc66866b4ac6cd8c5b8cce26
1 /*
2 * Copyright 2005, Jérôme Duval. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Inspired by SoundCapture from Be newsletter (Media Kit Basics:
6 * Consumers and Producers)
7 */
9 #include <stdio.h>
10 #include <string.h>
12 #include <MediaDefs.h>
13 #include <Screen.h>
14 #include <StackOrHeapArray.h>
15 #include <Window.h>
17 #include "DrawingTidbits.h"
18 #include "VUView.h"
20 const rgb_color back_color = {12, 36, 12};
21 const rgb_color low_color = {40, 120, 40};
22 const rgb_color high_color = {240, 255, 240};
24 VUView::VUView(BRect rect, uint32 resizeFlags)
25 : BView(rect, "vumeter", resizeFlags, B_WILL_DRAW),
26 fThreadId(-1),
27 fBitmap(NULL),
28 fQuitting(false)
30 rect.OffsetTo(B_ORIGIN);
31 fLevelCount = int(rect.Height()) / 2;
32 fChannels = 2;
33 fCurrentLevels = new int32[fChannels];
34 for (int channel = 0; channel < fChannels; channel++)
35 fCurrentLevels[channel] = 0;
36 fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true);
39 memset(fBitmap->Bits(), 0, fBitmap->BitsLength());
41 fBitmapView = new BView(rect, "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP,
42 B_WILL_DRAW);
43 fBitmap->AddChild(fBitmapView);
47 VUView::~VUView()
49 delete fBitmap;
53 void
54 VUView::AttachedToWindow()
56 SetViewColor(B_TRANSPARENT_COLOR);
57 _Run();
61 void
62 VUView::DetachedFromWindow()
64 _Quit();
68 void
69 VUView::Draw(BRect updateRect)
71 DrawBitmap(fBitmap);
73 Sync();
77 void
78 VUView::_Run()
80 fThreadId = spawn_thread(_RenderLaunch, "VU view", B_NORMAL_PRIORITY,
81 this);
82 if (fThreadId < 0)
83 return;
84 resume_thread(fThreadId);
87 void
88 VUView::_Quit()
90 fQuitting = true;
91 snooze(10000);
92 kill_thread(fThreadId);
97 int32
98 VUView::_RenderLaunch(void *data)
100 VUView *vu = (VUView*) data;
101 vu->_RenderLoop();
102 return B_OK;
106 #define SHIFT_UNTIL(value,shift,min) \
107 value = (value - shift > min) ? (value - shift) : min
109 void
110 VUView::_RenderLoop()
112 BStackOrHeapArray<rgb_color[2], 64> levels(fLevelCount);
114 for (int32 i = 0; i < fLevelCount; i++) {
115 levels[i][0] = levels[i][1] = back_color;
118 while (!fQuitting) {
120 /* computing */
121 for (int32 channel = 0; channel < 2; channel++) {
122 int32 level = fCurrentLevels[channel];
123 for (int32 i = 0; i < level; i++) {
124 if (levels[i][channel].red >= 90) {
125 SHIFT_UNTIL(levels[i][channel].red, 15, low_color.red);
126 SHIFT_UNTIL(levels[i][channel].blue, 15, low_color.blue);
127 } else {
128 SHIFT_UNTIL(levels[i][channel].red, 7, low_color.red);
129 SHIFT_UNTIL(levels[i][channel].blue, 7, low_color.blue);
130 SHIFT_UNTIL(levels[i][channel].green, 14, low_color.green);
134 levels[level][channel] = high_color;
136 for (int32 i = level + 1; i < fLevelCount; i++) {
137 if (levels[i][channel].red >= 85) {
138 SHIFT_UNTIL(levels[i][channel].red, 15, back_color.red);
139 SHIFT_UNTIL(levels[i][channel].blue, 15, back_color.blue);
140 } else {
141 SHIFT_UNTIL(levels[i][channel].red, 7, back_color.red);
142 SHIFT_UNTIL(levels[i][channel].blue, 7, back_color.blue);
143 SHIFT_UNTIL(levels[i][channel].green, 14,
144 back_color.green);
149 /* rendering */
150 fBitmap->Lock();
151 fBitmapView->BeginLineArray(fLevelCount * 2);
152 BPoint start1, end1, start2, end2;
153 start1.x = 3;
154 start2.x = 22;
155 end1.x = 16;
156 end2.x = 35;
157 start1.y = end1.y = start2.y = end2.y = 2;
158 for (int32 i = fLevelCount - 1; i >= 0; i--) {
159 fBitmapView->AddLine(start1, end1, levels[i][0]);
160 fBitmapView->AddLine(start2, end2, levels[i][1]);
161 start1.y = end1.y = start2.y = end2.y = end2.y + 2;
163 fBitmapView->EndLineArray();
164 fBitmap->Unlock();
166 /* ask drawing */
168 if (Window()->LockWithTimeout(5000) == B_OK) {
169 Invalidate();
170 Window()->Unlock();
171 snooze(50000);
177 template<typename T>
179 VUView::_ComputeNextLevel(const void *data, size_t size, uint32 format,
180 int32 channel)
182 const T* samp = (const T*)data;
184 // get the min and max values in the nibbling interval
185 // and set max to be the greater of the absolute value
186 // of these.
188 T min = 0, max = 0;
189 for (uint32 i = channel; i < size/sizeof(T); i += fChannels) {
190 if (min > samp[i])
191 min = samp[i];
192 else if (max < samp[i])
193 max = samp[i];
195 if (-max > (min + 1))
196 max = -min;
198 return max;
202 void
203 VUView::ComputeLevels(const void* data, size_t size, uint32 format)
205 for (int32 channel = 0; channel < fChannels; channel++) {
206 switch (format) {
207 case media_raw_audio_format::B_AUDIO_FLOAT:
209 float max = _ComputeNextLevel<float>(data, size, format,
210 channel);
211 fCurrentLevels[channel] = (uint8)(max * 127);
212 break;
214 case media_raw_audio_format::B_AUDIO_INT:
216 int32 max = _ComputeNextLevel<int32>(data, size, format,
217 channel);
218 fCurrentLevels[channel] = max / (2 << (32-7));
219 break;
221 case media_raw_audio_format::B_AUDIO_SHORT:
223 int16 max = _ComputeNextLevel<int16>(data, size, format,
224 channel);
225 fCurrentLevels[channel] = max / (2 << (16-7));
226 break;
228 case media_raw_audio_format::B_AUDIO_UCHAR:
230 uchar max = _ComputeNextLevel<uchar>(data, size, format,
231 channel);
232 fCurrentLevels[channel] = max / 2 - 127;
233 break;
235 case media_raw_audio_format::B_AUDIO_CHAR:
237 char max = _ComputeNextLevel<char>(data, size, format,
238 channel);
239 fCurrentLevels[channel] = max / 2;
240 break;
243 if (fCurrentLevels[channel] < 0)
244 fCurrentLevels[channel] = 0;