diff --git a/src/apps/soundrecorder/RecorderApp.cpp b/src/apps/soundrecorder/RecorderApp.cpp index 6a3837be4a..8561daf8a1 100644 --- a/src/apps/soundrecorder/RecorderApp.cpp +++ b/src/apps/soundrecorder/RecorderApp.cpp @@ -9,12 +9,13 @@ #include "RecorderWindow.h" -RecorderApp::RecorderApp(const char * signature) : - BApplication(signature), fRecorderWin(NULL) +RecorderApp::RecorderApp(const char* signature) + : BApplication(signature), fRecorderWin(NULL) { fRecorderWin = new RecorderWindow(); } + RecorderApp::~RecorderApp() { } diff --git a/src/apps/soundrecorder/RecorderApp.h b/src/apps/soundrecorder/RecorderApp.h index 953b585f65..19ccfecf89 100644 --- a/src/apps/soundrecorder/RecorderApp.h +++ b/src/apps/soundrecorder/RecorderApp.h @@ -13,12 +13,12 @@ class RecorderWindow; class RecorderApp : public BApplication { -public: - RecorderApp(const char * signature); - virtual ~RecorderApp(); - status_t InitCheck(); -private: - RecorderWindow* fRecorderWin; + public: + RecorderApp(const char * signature); + virtual ~RecorderApp(); + status_t InitCheck(); + private: + RecorderWindow* fRecorderWin; }; #endif /* RECORDERAPP_H */ diff --git a/src/apps/soundrecorder/RecorderWindow.cpp b/src/apps/soundrecorder/RecorderWindow.cpp index d0d8438729..e4d920a0ec 100644 --- a/src/apps/soundrecorder/RecorderWindow.cpp +++ b/src/apps/soundrecorder/RecorderWindow.cpp @@ -2,7 +2,8 @@ * Copyright 2005, Jérôme Duval. All rights reserved. * Distributed under the terms of the MIT License. * - * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: + * Consumers and Producers) */ #include @@ -61,7 +62,8 @@ static const float MIN_HEIGHT = 336.0f; static const float XPOS = 100.0f; static const float YPOS = 200.0f; -#define FOURCC(a,b,c,d) ((((uint32)(d)) << 24) | (((uint32)(c)) << 16) | (((uint32)(b)) << 8) | ((uint32)(a))) +#define FOURCC(a,b,c,d) ((((uint32)(d)) << 24) | (((uint32)(c)) << 16) \ + | (((uint32)(b)) << 8) | ((uint32)(a))) struct riff_struct { @@ -97,8 +99,8 @@ struct wave_struct RecorderWindow::RecorderWindow() : - BWindow(BRect(XPOS,YPOS,XPOS+MIN_WIDTH,YPOS+MIN_HEIGHT), "SoundRecorder", B_TITLED_WINDOW, - B_ASYNCHRONOUS_CONTROLS | B_NOT_V_RESIZABLE | B_NOT_ZOOMABLE), + BWindow(BRect(XPOS,YPOS,XPOS+MIN_WIDTH,YPOS+MIN_HEIGHT), "SoundRecorder", + B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_V_RESIZABLE | B_NOT_ZOOMABLE), fPlayer(NULL), fSoundList(NULL), fPlayFile(NULL), @@ -135,7 +137,7 @@ RecorderWindow::RecorderWindow() : RecorderWindow::~RecorderWindow() { - // The sound consumer and producer are Nodes; it has to be Release()d and the Roster + // The sound consumer and producer are Nodes; it has to be released and the Roster // will reap it when it's done. if (fRecordNode) { fRecordNode->Release(); @@ -154,9 +156,9 @@ RecorderWindow::~RecorderWindow() // Clean up items in list view. if (fSoundList) { fSoundList->DeselectAll(); - for (int ix=0; ixCountItems(); ix++) { - WINDOW((stderr, "clean up item %d\n", ix+1)); - SoundListItem * item = dynamic_cast(fSoundList->ItemAt(ix)); + for (int i = 0; i < fSoundList->CountItems(); i++) { + WINDOW((stderr, "clean up item %d\n", i+1)); + SoundListItem* item = dynamic_cast(fSoundList->ItemAt(i)); if (item) { if (item->IsTemp()) { item->Entry().Remove(); // delete temp file @@ -241,8 +243,8 @@ RecorderWindow::InitWindow() // Create the window header with controls BRect r(Bounds()); r.bottom = r.top + 175; - BBox *background = new BBox(r, "_background", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, - B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE_JUMP, B_NO_BORDER); + BBox *background = new BBox(r, "_background", B_FOLLOW_LEFT_RIGHT + | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, B_NO_BORDER); AddChild(background); @@ -265,7 +267,8 @@ RecorderWindow::InitWindow() r.right -= 26; r.top = 115; r.bottom = r.top + 30; - fTrackSlider = new TrackSlider(r, "trackSlider", new BMessage(POSITION_CHANGED), B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); + fTrackSlider = new TrackSlider(r, "trackSlider", new BMessage(POSITION_CHANGED), + B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); background->AddChild(fTrackSlider); BRect buttonRect; @@ -274,16 +277,16 @@ RecorderWindow::InitWindow() buttonRect = BRect(BPoint(0,0), kSkipButtonSize); buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-7, 25)); fRewindButton = new TransportButton(buttonRect, "Rewind", - kSkipBackBitmapBits, kPressedSkipBackBitmapBits, kDisabledSkipBackBitmapBits, - new BMessage(REWIND)); + kSkipBackBitmapBits, kPressedSkipBackBitmapBits, + kDisabledSkipBackBitmapBits, new BMessage(REWIND)); background->AddChild(fRewindButton); // Button for stopping recording or playback buttonRect = BRect(BPoint(0,0), kStopButtonSize); buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-48, 25)); fStopButton = new TransportButton(buttonRect, "Stop", - kStopButtonBitmapBits, kPressedStopButtonBitmapBits, kDisabledStopButtonBitmapBits, - new BMessage(STOP)); + kStopButtonBitmapBits, kPressedStopButtonBitmapBits, + kDisabledStopButtonBitmapBits, new BMessage(STOP)); background->AddChild(fStopButton); // Button for starting playback of selected sound @@ -297,8 +300,8 @@ RecorderWindow::InitWindow() buttonRect = BRect(BPoint(0,0), kSkipButtonSize); buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-133, 25)); fForwardButton = new TransportButton(buttonRect, "Forward", - kSkipForwardBitmapBits, kPressedSkipForwardBitmapBits, kDisabledSkipForwardBitmapBits, - new BMessage(FORWARD)); + kSkipForwardBitmapBits, kPressedSkipForwardBitmapBits, + kDisabledSkipForwardBitmapBits, new BMessage(FORWARD)); background->AddChild(fForwardButton); // Button to start recording (or waiting for sound) @@ -312,7 +315,8 @@ RecorderWindow::InitWindow() buttonRect = BRect(BPoint(0,0), kDiskButtonSize); buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-250, 21)); fSaveButton = new TransportButton(buttonRect, "Save", - kDiskButtonBitmapsBits, kPressedDiskButtonBitmapsBits, kDisabledDiskButtonBitmapsBits, new BMessage(SAVE)); + kDiskButtonBitmapsBits, kPressedDiskButtonBitmapsBits, + kDisabledDiskButtonBitmapsBits, new BMessage(SAVE)); fSaveButton->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); background->AddChild(fSaveButton); @@ -327,13 +331,15 @@ RecorderWindow::InitWindow() buttonRect = BRect(BPoint(0,0), kSpeakerIconBitmapSize); buttonRect.OffsetTo(background->Bounds().RightBottom() - BPoint(121, 17)); - SpeakerView *speakerView = new SpeakerView(buttonRect, B_FOLLOW_LEFT | B_FOLLOW_TOP); + SpeakerView *speakerView = new SpeakerView(buttonRect, + B_FOLLOW_LEFT | B_FOLLOW_TOP); speakerView->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); background->AddChild(speakerView); buttonRect = BRect(BPoint(0,0), BPoint(84, 19)); buttonRect.OffsetTo(background->Bounds().RightBottom() - BPoint(107, 20)); - fVolumeSlider = new VolumeSlider(buttonRect, "volumeSlider", B_FOLLOW_LEFT | B_FOLLOW_TOP); + fVolumeSlider = new VolumeSlider(buttonRect, "volumeSlider", + B_FOLLOW_LEFT | B_FOLLOW_TOP); fVolumeSlider->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); background->AddChild(fVolumeSlider); @@ -362,8 +368,8 @@ RecorderWindow::InitWindow() fSoundList = new SoundListView(r, "Sound List", B_FOLLOW_ALL); fSoundList->SetSelectionMessage(new BMessage(SOUND_SELECTED)); fSoundList->SetViewColor(216, 216, 216); - BScrollView *scroller = new BScrollView("scroller", fSoundList, B_FOLLOW_ALL, - 0, false, true, B_FANCY_BORDER); + BScrollView *scroller = new BScrollView("scroller", fSoundList, + B_FOLLOW_ALL, 0, false, true, B_FANCY_BORDER); fBottomBox->AddChild(scroller); r = fBottomBox->Bounds(); @@ -425,18 +431,19 @@ RecorderWindow::InitWindow() char selected_name[B_MEDIA_NAME_LENGTH] = "Default Input"; BMessage * msg; BMenuItem * item; - for (int ix=0; ixAddData("node", B_RAW_TYPE, &dni[ix], sizeof(dni[ix])); - item = new BMenuItem(dni[ix].name, msg); + msg->AddData("node", B_RAW_TYPE, &dni[i], sizeof(dni[i])); + item = new BMenuItem(dni[i].name, msg); popup->AddItem(item); media_node_id ni[12]; int32 ni_count = 12; - error = fRoster->GetInstancesFor(dni[ix].addon, dni[ix].flavor_id, ni, &ni_count); + error = fRoster->GetInstancesFor(dni[i].addon, dni[i].flavor_id, + ni, &ni_count); if (error == B_OK) - for (int iy=0; iyFindInt64("right", &right) == B_OK) { if (fPlayTrack) - fPlayLimit = MIN(fPlayFrames, (off_t)(right * fPlayFormat.u.raw_audio.frame_rate/1000000LL)); + fPlayLimit = MIN(fPlayFrames, + (off_t)(right * fPlayFormat.u.raw_audio.frame_rate/1000000LL)); fScopeView->SetRightTime(right); } if (message->FindInt64("left", &left) == B_OK) { @@ -632,7 +640,8 @@ RecorderWindow::Record(BMessage * message) } // Reserve space on disk (creates fewer fragments) err = fRecFile.SetSize(4 * fRecordFormat.u.raw_audio.channel_count - * fRecordFormat.u.raw_audio.frame_rate * (fRecordFormat.u.raw_audio.format & 0xf)); + * fRecordFormat.u.raw_audio.frame_rate * (fRecordFormat.u.raw_audio.format + & media_raw_audio_format::B_AUDIO_SIZE_MASK)); if (err < B_OK) { ErrorAlert("record a sound that long", err); fRecEntry.Remove(); @@ -653,10 +662,11 @@ RecorderWindow::Record(BMessage * message) } // And get it going... - bigtime_t then = fRecordNode->TimeSource()->Now()+50000LL; + bigtime_t then = fRecordNode->TimeSource()->Now() + 50000LL; fRoster->StartNode(fRecordNode->Node(), then); if (fAudioInputNode.kind & B_TIME_SOURCE) { - fRoster->StartNode(fAudioInputNode, fRecordNode->TimeSource()->RealTimeFor(then, 0)); + fRoster->StartNode(fAudioInputNode, + fRecordNode->TimeSource()->RealTimeFor(then, 0)); } else { fRoster->StartNode(fAudioInputNode, then); @@ -684,7 +694,8 @@ RecorderWindow::Play(BMessage * message) return; } - fPlayLimit = MIN(fPlayFrames, (off_t)(fTrackSlider->RightTime() * fPlayFormat.u.raw_audio.frame_rate / 1000000LL)); + fPlayLimit = MIN(fPlayFrames, (off_t)(fTrackSlider->RightTime() + * fPlayFormat.u.raw_audio.frame_rate / 1000000LL)); fPlayTrack->SeekToTime(fTrackSlider->MainTime()); fPlayFrame = fPlayTrack->CurrentFrame(); @@ -813,7 +824,8 @@ RecorderWindow::Selected(BMessage * message) return; status_t err = UpdatePlayFile(pItem, true); if (err != B_OK) { - ErrorAlert("recognize this file as a media file", err == B_MEDIA_NO_HANDLER ? B_OK : err); + ErrorAlert("recognize this file as a media file", + err == B_MEDIA_NO_HANDLER ? B_OK : err); RemoveCurrentSoundItem(); } UpdateButtons(); @@ -828,11 +840,13 @@ RecorderWindow::MakeRecordConnection(const media_node & input) int32 count = 0; status_t err = fRoster->GetFreeOutputsFor(input, &fAudioOutput, 1, &count, B_MEDIA_RAW_AUDIO); if (err < B_OK) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't get free outputs from audio input node\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " couldn't get free outputs from audio input node\n")); return err; } if (count < 1) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): no free outputs from audio input node\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " no free outputs from audio input node\n")); return B_BUSY; } @@ -843,11 +857,13 @@ RecorderWindow::MakeRecordConnection(const media_node & input) // TODO: explain this err = fRoster->GetFreeInputsFor(fRecordNode->Node(), &fRecInput, 1, &count, B_MEDIA_RAW_AUDIO); if (err < B_OK) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't get free inputs for sound recorder\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " couldn't get free inputs for sound recorder\n")); return err; } if (count < 1) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): no free inputs for sound recorder\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " no free inputs for sound recorder\n")); return B_BUSY; } @@ -863,14 +879,16 @@ RecorderWindow::MakeRecordConnection(const media_node & input) media_node use_time_source; BTimeSource * tsobj = fRoster->MakeTimeSourceFor(input); if (! tsobj) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't clone time source from audio input node\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " couldn't clone time source from audio input node\n")); return B_MEDIA_BAD_NODE; } // Apply the time source in effect to our own Node. err = fRoster->SetTimeSourceFor(fRecordNode->Node().node, tsobj->Node().node); if (err < B_OK) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't set the sound recorder's time source\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " couldn't set the sound recorder's time source\n")); tsobj->Release(); return err; } @@ -882,7 +900,8 @@ RecorderWindow::MakeRecordConnection(const media_node & input) // Tell the consumer where we want data to go. err = fRecordNode->SetHooks(RecordFile, NotifyRecordFile, this); if (err < B_OK) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't set the sound recorder's hook functions\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " couldn't set the sound recorder's hook functions\n")); tsobj->Release(); return err; } @@ -890,7 +909,8 @@ RecorderWindow::MakeRecordConnection(const media_node & input) // Using the same structs for input and output is OK in BMediaRoster::Connect(). err = fRoster->Connect(fAudioOutput.source, fRecInput.destination, &fRecordFormat, &fAudioOutput, &fRecInput); if (err < B_OK) { - CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): failed to connect sound recorder to audio input node.\n")); + CONNECT((stderr, "RecorderWindow::MakeRecordConnection():" + " failed to connect sound recorder to audio input node.\n")); tsobj->Release(); fRecordNode->SetHooks(0, 0, 0); return err; @@ -913,7 +933,8 @@ RecorderWindow::BreakRecordConnection() // If we are the last connection, the Node will stop automatically since it // has nowhere to send data to. err = fRoster->StopNode(fRecInput.node, 0); - err = fRoster->Disconnect(fAudioOutput.node.node, fAudioOutput.source, fRecInput.node.node, fRecInput.destination); + err = fRoster->Disconnect(fAudioOutput.node.node, fAudioOutput.source, + fRecInput.node.node, fRecInput.destination); fAudioOutput.source = media_source::null; fRecInput.destination = media_destination::null; return err; @@ -1175,8 +1196,8 @@ RecorderWindow::RemoveCurrentSoundItem() { void -RecorderWindow::RecordFile(void * cookie, bigtime_t timestamp, - void * data, size_t size, const media_raw_audio_format & format) +RecorderWindow::RecordFile(void* cookie, bigtime_t timestamp, + void* data, size_t size, const media_raw_audio_format &format) { // Callback called from the SoundConsumer when receiving buffers. RecorderWindow * window = (RecorderWindow *)cookie; @@ -1185,7 +1206,7 @@ RecorderWindow::RecordFile(void * cookie, bigtime_t timestamp, // Write the data to file (we don't buffer or guard file access // or anything) window->fRecFile.WriteAt(window->fRecSize, data, size); - window->fVUView->ComputeNextLevel(data, size); + window->fVUView->ComputeLevels(data, size, format.format); window->fRecSize += size; } } @@ -1204,7 +1225,8 @@ RecorderWindow::NotifyRecordFile(void * cookie, int32 code, ...) void -RecorderWindow::PlayFile(void * cookie, void * data, size_t size, const media_raw_audio_format & format) +RecorderWindow::PlayFile(void * cookie, void * data, size_t size, + const media_raw_audio_format & format) { // Callback called from the SoundProducer when producing buffers. RecorderWindow * window = (RecorderWindow *)cookie; @@ -1219,7 +1241,7 @@ RecorderWindow::PlayFile(void * cookie, void * data, size_t size, const media_ra } int64 frames = 0; window->fPlayTrack->ReadFrames(data, &frames); - window->fVUView->ComputeNextLevel(data, size/frame_size); + window->fVUView->ComputeLevels(data, size / frame_size, format.format); window->fPlayFrame += size/frame_size; window->PostMessage(UPDATE_TRACKSLIDER); } else { @@ -1229,7 +1251,8 @@ RecorderWindow::PlayFile(void * cookie, void * data, size_t size, const media_ra } void -RecorderWindow::NotifyPlayFile(void * cookie, BSoundPlayer::sound_player_notification code, ...) +RecorderWindow::NotifyPlayFile(void * cookie, + BSoundPlayer::sound_player_notification code, ...) { if ((code == BSoundPlayer::B_STOPPED) || (code == BSoundPlayer::B_SOUND_DONE)) { RecorderWindow * window = (RecorderWindow *)cookie; @@ -1300,7 +1323,8 @@ RecorderWindow::CopyTarget(BMessage *msg) // write data bigtime_t diffTime = fTrackSlider->RightTime() - fTrackSlider->LeftTime(); - int64 framesToWrite = (int64) (diffTime * fPlayFormat.u.raw_audio.frame_rate / 1000000LL); + int64 framesToWrite = (int64) (diffTime + * fPlayFormat.u.raw_audio.frame_rate / 1000000LL); int32 frameSize = (fPlayFormat.u.raw_audio.format & 0xf) * fPlayFormat.u.raw_audio.channel_count; diff --git a/src/apps/soundrecorder/ScopeView.cpp b/src/apps/soundrecorder/ScopeView.cpp index 9c83bbabd5..681150068b 100644 --- a/src/apps/soundrecorder/ScopeView.cpp +++ b/src/apps/soundrecorder/ScopeView.cpp @@ -2,7 +2,8 @@ * Copyright 2005, Jérôme Duval. All rights reserved. * Distributed under the terms of the MIT License. * - * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: + * Consumers and Producers) */ #include @@ -14,6 +15,8 @@ #include "DrawingTidbits.h" #include "ScopeView.h" +#define SAMPLES_COUNT 20000 + //#define TRACE 1 #ifdef TRACE #define TRACE(x...) printf(x) @@ -28,13 +31,11 @@ ScopeView::ScopeView(BRect rect, uint32 resizeFlags) fBitmapView(NULL), fIsRendering(false), fMediaTrack(NULL), - fQuitting(false), fMainTime(0), fRightTime(1000000), fLeftTime(0), fTotalTime(1000000) { - fRenderSem = create_sem(0, "scope rendering"); fHeight = Bounds().Height(); } @@ -75,7 +76,8 @@ ScopeView::Draw(BRect updateRect) float x = 2; if (fTotalTime !=0) - x = 2 + (fMainTime - fLeftTime) * (bounds.right - 2) / (fRightTime - fLeftTime); + x += (fMainTime - fLeftTime) * (bounds.right - 2) + / (fRightTime - fLeftTime); SetHighColor(60,255,40); StrokeLine(BPoint(x, bounds.top), BPoint(x, bounds.bottom)); @@ -86,7 +88,9 @@ ScopeView::Draw(BRect updateRect) void ScopeView::Run() { - fThreadId = spawn_thread(&RenderLaunch, "Scope view", B_NORMAL_PRIORITY, this); + fRenderSem = create_sem(0, "scope rendering"); + fThreadId = spawn_thread(&RenderLaunch, "Scope view", B_NORMAL_PRIORITY, + this); if (fThreadId < 0) return; resume_thread(fThreadId); @@ -96,7 +100,6 @@ void ScopeView::Quit() { delete_sem(fRenderSem); - fQuitting = true; snooze(10000); kill_thread(fThreadId); } @@ -112,51 +115,80 @@ ScopeView::RenderLaunch(void *data) } +template +void +ScopeView::ComputeRendering() +{ + int64 framesCount = fMediaTrack->CountFrames() / SAMPLES_COUNT; + T samples[fPlayFormat.u.raw_audio.buffer_size / (fPlayFormat.u.raw_audio.format + & media_raw_audio_format::B_AUDIO_SIZE_MASK)]; + int64 frames = 0; + U sum = 0; + int64 sumCount = 0; + float middle = fHeight / 2; + int32 previewMax = 0; + //fMediaTrack->SeekToFrame(&frames); + + TRACE("begin computing\n"); + + int32 previewIndex = 0; + + while (fIsRendering && fMediaTrack->ReadFrames(samples, &frames) == B_OK) { + //TRACE("reading block\n"); + int64 framesIndex = 0; + + while (framesIndex < frames) { + for (; framesIndex < frames && sumCount < framesCount; + framesIndex++, sumCount++) { + sum += samples[2 * framesIndex]; + sum += samples[2 * framesIndex + 1]; + } + + if (previewIndex >= SAMPLES_COUNT) + break; + + if (sumCount >= framesCount) { + //TRACE("computing block %ld, sumCount %ld\n", previewIndex, sumCount); + fPreview[previewIndex] = (int32)(sum + / fPlayFormat.u.raw_audio.channel_count / framesCount); + if (previewMax < fPreview[previewIndex]) + previewMax = fPreview[previewIndex]; + sumCount = 0; + sum = 0; + previewIndex++; + } + } + } + + for (int i = 0; i < SAMPLES_COUNT; i++) + fPreview[i] = (int32)(fPreview[i] * 1.0 / previewMax * middle + middle); +} + + void ScopeView::RenderLoop() { - while (!fQuitting) { - if (acquire_sem(fRenderSem)!=B_OK) - continue; - + while (acquire_sem(fRenderSem) == B_OK) { fIsRendering = true; - - //int32 frameSize = (fPlayFormat.u.raw_audio.format & 0xf) * fPlayFormat.u.raw_audio.channel_count; - int64 totalFrames = fMediaTrack->CountFrames(); - int16 samples[fPlayFormat.u.raw_audio.buffer_size / (fPlayFormat.u.raw_audio.format & 0xf)]; - int64 frames = 0; - int64 sum = 0; - int64 framesIndex = 0; - int32 sumCount = 0; - fMediaTrack->SeekToFrame(&frames); - - TRACE("begin computing\n"); - - int32 previewIndex = 0; - - while (fIsRendering && fMediaTrack->ReadFrames(samples, &frames) == B_OK) { - //TRACE("reading block\n"); - framesIndex = 0; - - while (framesIndex < frames) { - for (; framesIndex < frames && sumCount < totalFrames/20000; framesIndex++, sumCount++) { - sum += samples[2*framesIndex]; - sum += samples[2*framesIndex+1]; - } - - if (previewIndex >= 20000) { - break; - } - - if (sumCount >= totalFrames/20000) { - //TRACE("computing block %ld, sumCount %ld\n", previewIndex, sumCount); - fPreview[previewIndex++] = (int32)(sum / 2 /(totalFrames/20000) / 32767.0 * fHeight / 2 + fHeight / 2); - sumCount = 0; - sum = 0; - } - } - } + switch (fPlayFormat.u.raw_audio.format) { + case media_raw_audio_format::B_AUDIO_FLOAT: + ComputeRendering(); + break; + case media_raw_audio_format::B_AUDIO_INT: + ComputeRendering(); + break; + case media_raw_audio_format::B_AUDIO_SHORT: + ComputeRendering(); + break; + case media_raw_audio_format::B_AUDIO_UCHAR: + ComputeRendering(); + break; + case media_raw_audio_format::B_AUDIO_CHAR: + ComputeRendering(); + break; + } + TRACE("finished computing, rendering\n"); /* rendering */ @@ -223,7 +255,7 @@ ScopeView::RenderTrack(BMediaTrack *track, media_format format) { fMediaTrack = track; fPlayFormat = format; - release_sem(fRenderSem); + release_sem(fRenderSem); } @@ -304,7 +336,8 @@ ScopeView::InitBitmap() rect.OffsetToSelf(B_ORIGIN); rect.right -= 2; - fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW); + fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView", + B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW); fBitmap->AddChild(fBitmapView); } @@ -322,11 +355,14 @@ ScopeView::RenderBitmap() fBitmapView->SetDrawingMode(B_OP_ADD); fBitmapView->SetHighColor(15,60,15); - int32 leftIndex = (fTotalTime != 0) ? fLeftTime * 20000 / fTotalTime : 0; - int32 rightIndex = (fTotalTime != 0) ? fRightTime * 20000 / fTotalTime : 20000; + int32 leftIndex = + (fTotalTime != 0) ? fLeftTime * 20000 / fTotalTime : 0; + int32 rightIndex = + (fTotalTime != 0) ? fRightTime * 20000 / fTotalTime : 20000; for (int32 i = leftIndex; iStrokeLine(point, point); } diff --git a/src/apps/soundrecorder/ScopeView.h b/src/apps/soundrecorder/ScopeView.h index 4554d8f811..79db63c3c7 100644 --- a/src/apps/soundrecorder/ScopeView.h +++ b/src/apps/soundrecorder/ScopeView.h @@ -34,6 +34,7 @@ private: void Quit(); static int32 RenderLaunch(void *data); void RenderLoop(); + template void ComputeRendering(); void RenderBitmap(); void InitBitmap(); @@ -45,7 +46,6 @@ private: BMediaTrack *fMediaTrack; media_format fPlayFormat; - bool fQuitting; bigtime_t fMainTime; bigtime_t fRightTime; bigtime_t fLeftTime; diff --git a/src/apps/soundrecorder/TrackSlider.cpp b/src/apps/soundrecorder/TrackSlider.cpp index b4befb0d00..2b3c39377e 100644 --- a/src/apps/soundrecorder/TrackSlider.cpp +++ b/src/apps/soundrecorder/TrackSlider.cpp @@ -46,13 +46,13 @@ TrackSlider::AttachedToWindow() { BControl::AttachedToWindow(); SetViewColor(B_TRANSPARENT_COLOR); - InitBitmap(); - RenderBitmap(); + _InitBitmap(); + _RenderBitmap(); } void -TrackSlider::InitBitmap() +TrackSlider::_InitBitmap() { if (fBitmapView) { fBitmap->RemoveChild(fBitmapView); @@ -83,7 +83,7 @@ TrackSlider::InitBitmap() #define SLIDER_BASE 10 void -TrackSlider::RenderBitmap() +TrackSlider::_RenderBitmap() { /* rendering */ if (fBitmap->Lock()) { @@ -98,20 +98,20 @@ TrackSlider::Draw(BRect updateRect) { DrawBitmapAsync(fBitmap, BPoint(0,0)); - DrawCounter(fMainTime, fBitmapView->fPositionX, fMainTracking); + _DrawCounter(fMainTime, fBitmapView->fPositionX, fMainTracking); if (fLeftTracking) - DrawCounter(fLeftTime, fBitmapView->fLeftX, fLeftTracking); + _DrawCounter(fLeftTime, fBitmapView->fLeftX, fLeftTracking); else if (fRightTracking) - DrawCounter(fRightTime, fBitmapView->fRightX, fRightTracking); + _DrawCounter(fRightTime, fBitmapView->fRightX, fRightTracking); - DrawMarker(fBitmapView->fPositionX); + _DrawMarker(fBitmapView->fPositionX); Sync(); } void -TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking) +TrackSlider::_DrawCounter(bigtime_t timestamp, float position, bool isTracking) { // timecounter @@ -121,7 +121,7 @@ TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking) rgb_color white = {255,255,255}; char string[12]; - TimeToString(timestamp, string); + _TimeToString(timestamp, string); int32 halfwidth = ((int32)fFont.StringWidth(string)) / 2; float counterX = position; @@ -161,7 +161,7 @@ TrackSlider::DrawCounter(bigtime_t timestamp, float position, bool isTracking) void -TrackSlider::DrawMarker(float position) +TrackSlider::_DrawMarker(float position) { rgb_color black = {0,0,0}; rgb_color rose = {255,152,152}; @@ -221,7 +221,7 @@ TrackSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message) SetTracking(false); } - UpdatePosition(point); + _UpdatePosition(point); } @@ -231,7 +231,7 @@ TrackSlider::MouseDown(BPoint point) if (!Bounds().InsetBySelf(2,2).Contains(point)) return; - UpdatePosition(point); + _UpdatePosition(point); SetTracking(true); SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | B_LOCK_WINDOW_FOCUS); } @@ -243,7 +243,7 @@ TrackSlider::MouseUp(BPoint point) if (!IsTracking()) return; if (Bounds().InsetBySelf(2,2).Contains(point)) { - UpdatePosition(point); + _UpdatePosition(point); } fLeftTracking = fRightTracking = fMainTracking = false; @@ -256,7 +256,7 @@ TrackSlider::MouseUp(BPoint point) void -TrackSlider::UpdatePosition(BPoint point) +TrackSlider::_UpdatePosition(BPoint point) { BRect leftRect(fBitmapView->fLeftX-9, SLIDER_BASE+3, fBitmapView->fLeftX, SLIDER_BASE+16); BRect rightRect(fBitmapView->fRightX, SLIDER_BASE+3, fBitmapView->fRightX+9, SLIDER_BASE+16); @@ -283,7 +283,7 @@ TrackSlider::UpdatePosition(BPoint point) } Invoke(&msg); - RenderBitmap(); + _RenderBitmap(); //printf("fLeftPos : %Ld\n", fLeftTime); } else if (!fMainTracking && (fRightTracking || ((point.x > fBitmapView->fPositionX+4) && rightRect.Contains(point)))) { @@ -308,7 +308,7 @@ TrackSlider::UpdatePosition(BPoint point) } Invoke(&msg); - RenderBitmap(); + _RenderBitmap(); //printf("fRightPos : %Ld\n", fRightTime); } else { @@ -323,12 +323,12 @@ TrackSlider::UpdatePosition(BPoint point) fBitmapView->fRightX = fBitmapView->fPositionX; fRightTime = fMainTime; msg.AddInt64("right", fRightTime); - RenderBitmap(); + _RenderBitmap(); } else if (fBitmapView->fLeftX > fBitmapView->fPositionX) { fBitmapView->fLeftX = fBitmapView->fPositionX - 1; fLeftTime = fMainTime; msg.AddInt64("left", fLeftTime); - RenderBitmap(); + _RenderBitmap(); } Invoke(&msg); @@ -340,7 +340,7 @@ TrackSlider::UpdatePosition(BPoint point) void -TrackSlider::TimeToString(bigtime_t timestamp, char *string) +TrackSlider::_TimeToString(bigtime_t timestamp, char *string) { uint32 hours = timestamp / 3600000000LL; timestamp -= hours * 3600000000LL; @@ -364,7 +364,7 @@ TrackSlider::SetMainTime(bigtime_t timestamp, bool reset) fLeftTime = 0; fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime); fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime); - RenderBitmap(); + _RenderBitmap(); } Invalidate(); } @@ -381,7 +381,7 @@ TrackSlider::SetTotalTime(bigtime_t timestamp, bool reset) fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime); fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime); fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime); - RenderBitmap(); + _RenderBitmap(); Invalidate(); } @@ -400,10 +400,10 @@ TrackSlider::FrameResized(float width, float height) { fBitmapView->fRight = Bounds().right - kLeftRightTrackSliderWidth; fBitmapView->fPositionX = 15 + (fBitmapView->fRight - 14) * ((double)fMainTime / fTotalTime); - InitBitmap(); + _InitBitmap(); fBitmapView->fLeftX = 14 + (fBitmapView->fRight - 15) * ((double)fLeftTime / fTotalTime); fBitmapView->fRightX = 15 + (fBitmapView->fRight - 16) * ((double)fRightTime / fTotalTime); - RenderBitmap(); + _RenderBitmap(); Invalidate(); } diff --git a/src/apps/soundrecorder/TrackSlider.h b/src/apps/soundrecorder/TrackSlider.h index 711ebf41bf..3564cafe75 100644 --- a/src/apps/soundrecorder/TrackSlider.h +++ b/src/apps/soundrecorder/TrackSlider.h @@ -46,12 +46,12 @@ public: void ResetMainTime(); virtual void FrameResized(float width, float height); private: - void DrawCounter(bigtime_t timestamp, float position, bool isTracking); - void DrawMarker(float position); - void TimeToString(bigtime_t timestamp, char *string); - void UpdatePosition(BPoint point); - void InitBitmap(); - void RenderBitmap(); + void _DrawCounter(bigtime_t timestamp, float position, bool isTracking); + void _DrawMarker(float position); + void _TimeToString(bigtime_t timestamp, char *string); + void _UpdatePosition(BPoint point); + void _InitBitmap(); + void _RenderBitmap(); bigtime_t fLeftTime; diff --git a/src/apps/soundrecorder/VUView.cpp b/src/apps/soundrecorder/VUView.cpp index 549acbe482..d634474386 100644 --- a/src/apps/soundrecorder/VUView.cpp +++ b/src/apps/soundrecorder/VUView.cpp @@ -2,13 +2,17 @@ * Copyright 2005, Jérôme Duval. All rights reserved. * Distributed under the terms of the MIT License. * - * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: + * Consumers and Producers) */ #include #include + +#include #include #include + #include "DrawingTidbits.h" #include "VUView.h" @@ -26,21 +30,22 @@ VUView::VUView(BRect rect, uint32 resizeFlags) fLevelCount = int(rect.Height()) / 2; fChannels = 2; fCurrentLevels = new int32[fChannels]; - for (int channel=0; channel < fChannels; channel++) + for (int channel = 0; channel < fChannels; channel++) fCurrentLevels[channel] = 0; fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true); memset(fBitmap->Bits(), 0, fBitmap->BitsLength()); - fBitmapView = new BView(rect, "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW); + fBitmapView = new BView(rect, "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, + B_WILL_DRAW); fBitmap->AddChild(fBitmapView); } VUView::~VUView() { - + delete fBitmap; } @@ -48,14 +53,14 @@ void VUView::AttachedToWindow() { SetViewColor(B_TRANSPARENT_COLOR); - Run(); + _Run(); } void VUView::DetachedFromWindow() { - Quit(); + _Quit(); } @@ -69,16 +74,16 @@ VUView::Draw(BRect updateRect) void -VUView::Run() +VUView::_Run() { - fThreadId = spawn_thread(&RenderLaunch, "VU view", B_NORMAL_PRIORITY, this); + fThreadId = spawn_thread(_RenderLaunch, "VU view", B_NORMAL_PRIORITY, this); if (fThreadId < 0) return; resume_thread(fThreadId); } void -VUView::Quit() +VUView::_Quit() { fQuitting = true; snooze(10000); @@ -88,18 +93,19 @@ VUView::Quit() int32 -VUView::RenderLaunch(void *data) +VUView::_RenderLaunch(void *data) { VUView *vu = (VUView*) data; - vu->RenderLoop(); + vu->_RenderLoop(); return B_OK; } -#define SHIFT_UNTIL(value,shift,min) value = (value - shift > min) ? (value - shift) : min +#define SHIFT_UNTIL(value,shift,min) \ + value = (value - shift > min) ? (value - shift) : min void -VUView::RenderLoop() +VUView::_RenderLoop() { rgb_color levels[fLevelCount][2]; @@ -167,29 +173,72 @@ VUView::RenderLoop() } -void -VUView::ComputeNextLevel(void *data, size_t size) +template +T +VUView::_ComputeNextLevel(void *data, size_t size, uint32 format, int32 channel) { - int16* samp = (int16*)data; + T* samp = (T*)data; + // get the min and max values in the nibbling interval + // and set max to be the greater of the absolute value + // of these. + + T min = 0, max = 0; + for (uint32 i = channel; i < size/sizeof(T); i += fChannels) { + if (min > samp[i]) + min = samp[i]; + else if (max < samp[i]) + max = samp[i]; + } + if (-max > (min + 1)) + max = -min; + + return max; +} + + +void +VUView::ComputeLevels(void* data, size_t size, uint32 format) +{ for (int32 channel = 0; channel < fChannels; channel++) { - - // get the min and max values in the nibbling interval - // and set max to be the greater of the absolute value - // of these. - - int mi = 0, ma = 0; - for (uint32 ix=channel; ix samp[ix]) mi = samp[ix]; - else if (ma < samp[ix]) ma = samp[ix]; + switch (format) { + case media_raw_audio_format::B_AUDIO_FLOAT: + { + float max = _ComputeNextLevel(data, size, format, + channel); + fCurrentLevels[channel] = (uint8)(max * 127); + break; + } + case media_raw_audio_format::B_AUDIO_INT: + { + int32 max = _ComputeNextLevel(data, size, format, + channel); + fCurrentLevels[channel] = max / (2 << (32-8)); + break; + } + case media_raw_audio_format::B_AUDIO_SHORT: + { + int16 max = _ComputeNextLevel(data, size, format, + channel); + fCurrentLevels[channel] = max / (2 << (16-7)); + break; + } + case media_raw_audio_format::B_AUDIO_UCHAR: + { + uchar max = _ComputeNextLevel(data, size, format, + channel); + fCurrentLevels[channel] = max / 2 - 127; + break; + } + case media_raw_audio_format::B_AUDIO_CHAR: + { + char max = _ComputeNextLevel(data, size, format, + channel); + fCurrentLevels[channel] = max / 2; + break; + } } - if (-ma > mi) ma = (mi == -32768) ? 32767 : -mi; - - uint8 n = ma / (2 << (16-7)); - - fCurrentLevels[channel] = n; if (fCurrentLevels[channel] < 0) fCurrentLevels[channel] = 0; } - } diff --git a/src/apps/soundrecorder/VUView.h b/src/apps/soundrecorder/VUView.h index bf6a70298f..4784c11992 100644 --- a/src/apps/soundrecorder/VUView.h +++ b/src/apps/soundrecorder/VUView.h @@ -2,7 +2,8 @@ * Copyright 2005, Jérôme Duval. All rights reserved. * Distributed under the terms of the MIT License. * - * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: + * Consumers and Producers) */ #ifndef VUVIEW_H @@ -20,13 +21,15 @@ public: void AttachedToWindow(); void DetachedFromWindow(); void Draw(BRect updateRect); - void ComputeNextLevel(void *data, size_t size); - + void ComputeLevels(void* data, size_t size, uint32 format); + private: - void Run(); - void Quit(); - static int32 RenderLaunch(void *data); - void RenderLoop(); + void _Run(); + void _Quit(); + static int32 _RenderLaunch(void *data); + void _RenderLoop(); + template T _ComputeNextLevel(void *data, + size_t size, uint32 format, int32 channel); thread_id fThreadId; BBitmap *fBitmap; diff --git a/src/apps/soundrecorder/VolumeSlider.cpp b/src/apps/soundrecorder/VolumeSlider.cpp index 6627b759d6..f7ba4ecdf3 100644 --- a/src/apps/soundrecorder/VolumeSlider.cpp +++ b/src/apps/soundrecorder/VolumeSlider.cpp @@ -99,7 +99,7 @@ VolumeSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message) if (!fSoundPlayer || !Bounds().InsetBySelf(2,2).Contains(point)) return; - UpdateVolume(point); + _UpdateVolume(point); } @@ -109,7 +109,7 @@ VolumeSlider::MouseDown(BPoint point) if (!fSoundPlayer || !Bounds().InsetBySelf(2,2).Contains(point)) return; - UpdateVolume(point); + _UpdateVolume(point); SetTracking(true); SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); } @@ -121,7 +121,7 @@ VolumeSlider::MouseUp(BPoint point) if (!IsTracking()) return; if (fSoundPlayer && Bounds().InsetBySelf(2,2).Contains(point)) { - UpdateVolume(point); + _UpdateVolume(point); } Invoke(); @@ -132,7 +132,7 @@ VolumeSlider::MouseUp(BPoint point) void -VolumeSlider::UpdateVolume(BPoint point) +VolumeSlider::_UpdateVolume(BPoint point) { fVolume = MIN(MAX(point.x, 11), fRight); fVolume = (fVolume - 11) / (fRight - 11); diff --git a/src/apps/soundrecorder/VolumeSlider.h b/src/apps/soundrecorder/VolumeSlider.h index 132890a732..ea3237b97d 100644 --- a/src/apps/soundrecorder/VolumeSlider.h +++ b/src/apps/soundrecorder/VolumeSlider.h @@ -23,7 +23,8 @@ public: virtual void MouseDown(BPoint point); void SetSoundPlayer(BSoundPlayer *player); private: - void UpdateVolume(BPoint point); + void _UpdateVolume(BPoint point); + BBitmap fLeftBitmap, fRightBitmap, fButtonBitmap; float fRight; float fVolume;