LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-21-2021, 08:52 AM   #1
apoorv569
Member
 
Registered: Jun 2020
Distribution: Arch Linux
Posts: 61

Rep: Reputation: 0
Question wxWidgets - Having problem with audio seeking a little before from the specified position.


I have a application that I'm currently developing, and I'm having a problem, that I'm not able to figure out. The application is for managing and auditioning audio samples, and I'm using wxWidgets as the GUI toolkit. Recently I was trying to implement looping a selected region. I have it working for the most part. The only problem I'm facing is that, say I have 2 points set, A and B, A is at 500 and B at 700 in milliseconds, I am doing a little match to calculate these points to pixel position on the screen to show the playhead and selected region points, the problem is that when my playhead reaches point B, and its time go back to A and play the sample again, to essentially loop, it goes back a little before point A i.e 450 or something for example, and I'm pretty sure my calculations are correct, don't know what is causing this issue. Here is a little GIF showing the problem hopefully this explains.

Here is some of the code related to the problem,

Here I calculate the position for the loop points A and B from pixel position to milliseconds, this is a custom event that I defined to send this information from one class to another.
Code:
void WaveformViewer::SendLoopPoints()
{
    wxLogDebug("%s Called", __FUNCTION__);

    SampleHive::SH_LoopPointsEvent event(SampleHive::SH_EVT_LOOP_POINTS_UPDATED, this->GetId());
    event.SetEventObject(this);

    Database db(m_InfoBar);

    int selected_row = m_Library.GetSelectedRow();

    if (selected_row < 0)
        return;

    wxString selected = m_Library.GetTextValue(selected_row, 1);
    std::string path = db.GetSamplePathByFilename(m_DatabaseFilepath, selected.BeforeLast('.').ToStdString());

    Tags tags(path);

    int length = tags.GetAudioInfo().length;

    int panel_width = this->GetSize().GetWidth();

    int a = m_AnchorPoint.x, b = m_CurrentPoint.x;

    double loopA = ((double)a / panel_width) * length;
    double loopB = ((double)b / panel_width) * length;

    event.SetLoopPoints({ loopA, loopB });

    HandleWindowEvent(event);

    wxLogDebug("%s processed event, sending loop points..", __FUNCTION__);
}
And I receive this custom event in my MainFrame class, and use these points to seek the audio sample from point A to B to loop between these points.
Code:
void MainFrame::OnRecieveLoopPoints(SampleHive::SH_LoopPointsEvent& event)
{
    wxLogDebug("%s called and recieved loop points", __FUNCTION__);

    std::pair<double, double> loop_points = event.GetLoopPoints();

    m_LoopA = wxLongLong(loop_points.first);
    m_LoopB = wxLongLong(loop_points.second);

    int loopA_min = static_cast<int>((m_LoopA / 60000).GetValue());
    int loopA_sec = static_cast<int>(((m_LoopA % 60000) / 1000).GetValue());
    int loopB_min = static_cast<int>((m_LoopB / 60000).GetValue());
    int loopB_sec = static_cast<int>(((m_LoopB % 60000) / 1000).GetValue());

    wxLogDebug(wxString::Format("LoopA: %2i:%02i, LoopB: %2i:%02i",
                                loopA_min, loopA_sec, loopB_min, loopB_sec));

    m_LoopPointAText->SetValue(wxString::Format("%2i:%02i", loopA_min, loopA_sec));
    m_LoopPointBText->SetValue(wxString::Format("%2i:%02i", loopB_min, loopB_sec));

    wxLogDebug("%s Event processed successfully..", __FUNCTION__);
}
Here I start the loop process, this is one of the methods to play the audio sample,
Code:
void MainFrame::OnClickPlay(wxCommandEvent& event)
{
    bStopped = false;

    int selected_row = m_Library->GetSelectedRow();

    if (selected_row < 0)
        return;

    wxString selection = m_Library->GetTextValue(selected_row, 1);

    wxString sample_path = GetFilenamePathAndExtension(selection).Path;

    if (bLoop && m_LoopPointAButton->GetValue() && m_LoopPointBButton->GetValue())
        PlaySample(sample_path.ToStdString(), selection.ToStdString(), true, m_LoopA.ToDouble(), wxFromStart);
    else
        PlaySample(sample_path.ToStdString(), selection.ToStdString());
}
PlaySample() is a function I defined so I can have one place where the wxTimer starts,
Code:
void MainFrame::PlaySample(const std::string& filepath, const std::string& sample, bool seek, wxFileOffset where, wxSeekMode mode)
{
    wxLogDebug("TIMER STARTING FROM %s", __FUNCTION__);

    if (m_MediaCtrl->Load(filepath))
    {
        if (seek)
            m_MediaCtrl->Seek(where, mode);

        if (!m_MediaCtrl->Play())
            wxLogDebug(_("Error! Cannot play sample."));

        PushStatusText(wxString::Format(_("Now playing: %s"), sample), 1);

        if (!m_Timer->IsRunning())
            m_Timer->Start(20, wxTIMER_CONTINUOUS);
    }
    else
        wxLogDebug(_("Error! Cannot load sample."));
}
And here I check if playhead is at point B, if it is go back to point A and play again, this is wxTimer event handler,
Code:
void MainFrame::UpdateElapsedTime(wxTimerEvent& event)
{
    wxLogDebug("TIMER IS RUNNING..");

    wxString duration, position;
    wxLongLong llLength, llTell;

    llLength = m_MediaCtrl->Length();
    int total_min = static_cast<int>((llLength / 60000).GetValue());
    int total_sec = static_cast<int>(((llLength % 60000) / 1000).GetValue());

    llTell = m_MediaCtrl->Tell();
    int current_min = static_cast<int>((llTell / 60000).GetValue());
    int current_sec = static_cast<int>(((llTell % 60000) / 1000).GetValue());

    duration.Printf(wxT("%2i:%02i"), total_min, total_sec);
    position.Printf(wxT("%2i:%02i"), current_min, current_sec);

    m_SamplePosition->SetLabel(wxString::Format(wxT("%s/%s"), position.c_str(), duration.c_str()));

    m_TopControlsPanel->Refresh();
    m_TopWaveformPanel->Refresh();

    if (bLoop && m_LoopPointAButton->GetValue() && m_LoopPointBButton->GetValue())
        if (static_cast<double>(m_MediaCtrl->Tell()) >= m_LoopB.ToDouble())
            m_MediaCtrl->Seek(m_LoopA.ToDouble(), wxFromStart);
}
Here is the link to full project if needed- SampleHive

This specific feature that I'm asking for help right now, is currently in the experimental-draw-waveform branch only.

Last edited by apoorv569; 09-22-2021 at 11:09 PM.
 
Old 09-28-2021, 03:11 PM   #2
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,263
Blog Entries: 24

Rep: Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194Reputation: 4194
As no one has replied I can only offer my own thoughts after having read your post several times...

First, I think your question may seem too much like asking for others to develop the application for you as opposed to asking for help solving a specific programming problem. I have read your post to try to understand what may not be working in your code, but always end up asking myself what it should be doing, so it is impossible to then say why it is not doing that! It seems that you are not asking a very specific question.

You may find it helpful to review the Site FAQ for guidance in asking well formed questions. Especially visit the link from that page, How to Ask Questions the Smart Way for discussion of things to consider when asking others for help.

The better you can refine your own understanding of your project code the better you may be able to reduce it to a specific, minimal example to provide when asking others for help.

Hope this helps!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Is it OK to do this? Send in a resume with no position specified snowmagician General 17 04-08-2017 03:42 PM
HTML/CSS/JS: Problem with <p> not having an absolute position with CSS. RHLinuxGUY Programming 7 03-03-2007 12:21 AM
problem in configuring wxwidgets ra2000 Programming 1 11-30-2006 04:21 AM
just 1 little problem to solve before I can run GTA III in wine plz help! vegetassj2 Linux - Games 2 04-27-2005 11:20 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:59 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration