Need help with pitch shifting 2 sounds at once

What I’m trying to do is I have each open guitar string recorded and I’m pitch shifting to reach the other notes and I’m trying to play 2 pitch shifted notes at the same time so I can hear the harmony but whenever I add the second pitch shift it just plays only the 1 note instead of both at the same time this is how I’m doing it please let me know what I’m doing wrong.

system2->update();
FMOD_RESULT result = system2->playSound(notehE, nullptr, true, &channel1);

channel1->setPitch(pitchMultiplier);
FMOD_RESULT result2 = system2->playSound(notehB, nullptr, true, &channel2);
channel2->setPitch(pitchMultiplier2);

Unfortunately, I haven’t been able to reproduce the issue you’re describing with the code snippet you’ve provided - I’m able to play and adjust the pitch of both channels without any problems. If possible, could I get you to provide the full code snippet (or a stripped down version of it where you can reproduce the issue) where you play both sounds? You can post it to the thread, link it from elsewhere, or upload to your FMOD User profile if needed.

Thank you so much for trying to help me I appreciate it so much. Ill show you exactly what I’m trying to do . Basically I have 2 groups of 6x16 edit boxes each group represents a guitar so guitar 1 and 2 . The 6 rows being the strings and columns are how many notes you can input. I only recorded the guitar strings open and then I used pitch shifting to play the other notes. Guitar 1 or 2 plays perfectly by themselves and heres there code for guitar 1:

case IDplay1:
{

   WCHAR buffer[256];
   for (int fret = 0; fret < 16; ++fret)
   {
       GetWindowText(hwndInput[0][fret], buffer, 256);
       std::wstring inputStr(buffer);
       if (!inputStr.empty())
       {
         
   WCHAR buffer[256];

   for (int fret = 0; fret < 16; ++fret)
   {
       system2->update();  

       for (int stringIndex = 0; stringIndex < 6; ++stringIndex)
       {
           GetWindowText(hwndInput[stringIndex][fret], buffer, 256);
           std::wstring inputStr(buffer);

           if (!inputStr.empty())
           {
               int interval = _wtoi(buffer);
               pitchMultiplier = std::pow(2.0f, static_cast<float>(interval) / 12.0f);

               // Adjust the note based on the current string
               FMOD::Sound* currentNote;
               switch (stringIndex)
               {
               case 0: currentNote = notehE; break;
               case 1: currentNote = notehB; break;
               case 2: currentNote = notehG; break;
               case 3: currentNote = notehD; break;
               case 4: currentNote = notehA; break;
               case 5: currentNote = noteLE; break;
               default: currentNote = noteLE;  break;
                
               }

               system2->playSound(currentNote, nullptr, false, &channel1);
               channel1->setPitch(pitchMultiplier);

               Sleep(500);  // Adjust the delay as needed
           }
       }
   }

break;
}

So if you hit play button it plays each note you inputed 1 at a time till it reachs the end and stops it works great. Guitar 2 is exaclty the same except its getting its input from the 2nd group of 6x16.

What I want to do is have a button where I click it and it plays guitar 1 and 2 at the same time letting you hear the harmony . I’ve tried to do it a couple different ways and none have worked. I simplified the source code and I found out it worked as long as I only pitch shifted the first channel . The second I try to pitch shift channel2 at the same time it only plays one channel. This is my simplification code :

case togetherB:
{
unsigned long long dspClockStart, dspClockEnd;
unsigned long long delayBetweenPlays = 48000 * 2;
unsigned long long playDuration = 48000; // Duration of the sound to play,

 // Retrieve the initial DSP clock values
 unsigned long long initialDSPClock, currentDSPClock;
 system2->getMasterChannelGroup(&masterGroup);
 masterGroup->getDSPClock(&currentDSPClock, &initialDSPClock);

 // Play the sound 5 times every 2 seconds
 for (int i = 0; i < 5; ++i)
 {
     // Calculate the DSP clock start time for the current iteration
     dspClockStart = initialDSPClock + i * delayBetweenPlays;

     // Calculate the end time, assuming the note plays for its entire duration
     dspClockEnd = dspClockStart + playDuration;

    
     FMOD_RESULT result = system2->playSound(notehE, nullptr, true,&channel1);
    channel1->setPitch(pitchMultiplier);
     FMOD_RESULT result2 = system2->playSound(notehB,nullptr,true,&channel2);
    system2->update();
 channel2->setPitch(pitchMultiplier2);
  
     if (result == FMOD_OK && result2 == FMOD_OK) {
         // Set the channel to start and end at the specific times calculated
         channel1->setDelay(dspClockStart, dspClockEnd, false);
         channel2->setDelay(dspClockStart, dspClockEnd, false);
         // Unpause the channel to start playing
         channel1->setPaused(false);
        
         channel2->setPaused(false);
     }
     else {
         // Handle error
         std::cerr << "Failed to play sound: " << result << std::endl;
     }

  }
 break;

}

when I comment out the second pitch shift they play together but when I add the second pitch shift only 1 plays so I figured where I was messing up in my actual program was trying to pitch shift 2 channels at same time. If you want I can put my whole source code if this is confusing…all the variables you see here that I didnt define are global variables . Thank you again for even trying to help me.

Heres my whole source :

#include <Windows.h>
#include <vector>
#include <string>
#include <sstream>
#include <map>
#include "fmod.hpp"
#include <thread>
#include <iostream>


FMOD::System* system2;
FMOD::Sound* notehE;
FMOD::Sound* notehB;
FMOD::Sound* notehG;
FMOD::Sound* notehD;
FMOD::Sound* notehA;
FMOD::Sound* noteLE;
FMOD::Channel* channel1;
FMOD::Channel* channel2;
FMOD::Channel* channel3;
FMOD::Channel* channel4;
FMOD::Channel* channel5;
FMOD::Sound* currentNote;
FMOD::Sound* currentNote2;
FMOD::ChannelGroup* masterGroup = nullptr;
FMOD::DSP* dspPitchShift;

HWND hBackground;
HWND hOverlay;
HINSTANCE hInst;
float pitchMultiplier = 1;
float pitchMultiplier1 = 2;
float pitchMultiplier2 = 0;

const int PLAYBACK_TIMER_ID = 105; // Unique timer ID
int currentFret = 0; // Global variable to track the current fret being played
bool isPlaying = false;


const int IDplay1 = 301; // Unique identifier for the first play button
const int IDplay2 = 302;
const int IDplay3 = 310;

std::vector<std::vector<int>> harmony(6, std::vector<int>(16, -1));


    int fretNumber;
    std::wistringstream iss(input);


int bString = 1;
int gString = 2;





// Function to validate the fret input
std::vector<std::vector<int>> CalculateHarmony(const std::vector<std::vector<int>>& inputFretNumbers) {
    // Map fret numbers on the high E string to the B string for the C Major scale
    std::map<int, int> eToBMapping = {
        {0, 1},  // E to C
        {1, 3},  // F to D
        {3, 5},  // G to E
        {5, 6},  // A to F
        {7, 8},  // B to G
        {8, 10}, // C to A
        {10, 12},// D to B
        {12, 13}, // E c
        {13, 15},  // F to D
        {15, 17},  // G to E
        {17, 18},  // A to F
        {19, 20},  // B to G
        {20, 22}, // C to A
        {22, 24}// D to B
     
    };
    std::map<int, int> bToGMapping = {
     {0, 0},  // b g
     {1, 2},  // c a
     {3, 4},  // d b
     {5, 5},  // e c
     {6, 7},  // f d
     {8, 9}, // g e
     {10, 10},// a f
     {12, 12}, // b g
     {13, 14},  // c a
     {15, 16},  // d b
     {17, 17},  // e c
     {18, 19},  // f d
     {20, 21}, // g e
     {22, 22},// a f
     {24, 24} // b g
    };
    std::map<int, int> gToDMapping = {
     {0, 2},  // g e
     {2, 3},  // a f
     {4, 5},  // b g
     {5, 7},  // c a
     {7, 9},  // d b
     {8, 10}, // e c
     {10, 12},// f d
     {12, 13}, // g e
     {14, 15},  // a f
     {16, 17},  // b g
     {17, 19},  // c a
     {19, 21},  // d b
     {20, 22}, // e c
     {22, 24}// f d
    };
    std::map<int, int> dToAMapping = {
     {0, 2},  // d b
     {2, 3},  // e c
     {3, 5},  // f d
     {5, 7},  // g e
     {7, 8},  // a f
     {9, 10}, // b g
     {10, 12},// c a
     {12, 14}, // d b
     {14, 15},  // e c
     {15, 17},  // f d
     {17, 19},  // g e
     {19, 20},  // a f
     {21, 22}, // b g
     {22, 24}// c a
    };
    std::map<int, int> aToEMapping = {
     {0, 1},  // a f
     {2, 3},  // b g
     {3, 5},  // c a
     {5, 7},  // d b
     {7, 8},  // e c
     {8, 10}, // f d
     {10, 12},// g e
     {12, 13}, // a f
     {14, 15},  // b g
     {15, 17},  // c a
     {17, 19},  // d b
     {19, 20},  // e c
     {20, 22}, // f d
     {22, 24}// g e
    };
    std::map<int, int> eToEMapping = {
 {3, 0},  // g e
 {5, 1},  // a f
 {7, 3},  // b g
 {8, 5},  // c a
 {10, 7},  // d b
 {12, 8}, // e c
 {13, 10},// f d
 {15, 12}, // g e
  {17, 13},  // a f
 {19, 15},  // b g
 {20, 17},  // c a
 {22, 19},  // d b
 {24, 20} // e c

    };

    //std::vector<std::vector<int>> harmony(6, std::vector<int>(16, -1)); // Initialize with -1 for unplayed strings

    // High E string is the 0th string in this context
    for (int string = 0; string < 6; ++string) {
        for (int fret = 0; fret < 16; ++fret) {
            int inputFret = inputFretNumbers[string][fret];
            std::map<int, int>* currentMapping = nullptr;

            // Select the appropriate mapping based on the string
            switch (string) {
            case 0: currentMapping = &eToBMapping; break;
            case 1: currentMapping = &bToGMapping; break;
            case 2: currentMapping = &gToDMapping; break;
            case 3: currentMapping = &dToAMapping; break;
            case 4: currentMapping = &aToEMapping; break;
            case 5: currentMapping = &eToEMapping; break;
                // Add cases for other strings...
            }

            // Validate inputFret and apply mapping
            if (inputFret >= 0 && currentMapping && currentMapping->find(inputFret) != currentMapping->end()) {
                harmony[string][fret] = (*currentMapping)[inputFret];
            }
        }
    }

    return harmony;
}




HWND hwndInput[6][16]; // Input edit boxes (6 strings, 16 frets)
HWND hwndOutput[6][16]; // Output edit boxes (for displaying harmony notes)

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
    {
        const int fGrp = 4;
        const int spaceG = 10;
        InitializeFretboard();
        FMOD::System_Create(&system2);
        system2->init(1024, FMOD_INIT_NORMAL, 0);
        system2->createSound("he.wav", FMOD_DEFAULT, 0, &notehE);
        system2->createSound("b.wav", FMOD_DEFAULT, 0, &notehB);
        system2->createSound("g.wav", FMOD_DEFAULT, 0, &notehG);
        system2->createSound("d.wav", FMOD_DEFAULT, 0, &notehD);
        system2->createSound("a.wav", FMOD_DEFAULT, 0, &notehA);
        system2->createSound("lowE.wav", FMOD_DEFAULT, 0, &noteLE);

        for (int string = 0; string < 6; ++string)
        {
            for (int fret = 0; fret < 16; ++fret)
            {
                hwndInput[string][fret] = CreateWindowEx(0, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER, 20 + fret * 40, 20 + string * 20, 20, 20, hwnd, NULL, NULL, NULL);
                hwndOutput[string][fret] = CreateWindowEx(0, L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY, 20 + fret * 40, 300 + string * 20, 20, 20, hwnd, NULL, NULL, NULL);
            }
        }

        CreateWindow(L"BUTTON", L"Generate", WS_CHILD | WS_VISIBLE, 20, 500, 80, 30, hwnd, (HMENU)IDOK, NULL, NULL);
        CreateWindow(L"BUTTON", L"play #1", WS_CHILD | WS_VISIBLE, 670, 70, 80, 30, hwnd, (HMENU)IDplay1, NULL, NULL);
        CreateWindow(L"BUTTON", L"play #2", WS_CHILD | WS_VISIBLE, 670, 350, 80, 30, hwnd, (HMENU)IDplay2, NULL, NULL);
        CreateWindow(L"BUTTON", L"together", WS_CHILD | WS_VISIBLE, 100, 500, 80, 30, hwnd, (HMENU)IDplay3, NULL, NULL);
        break;
    }
    case WM_PAINT:
    {

        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        HBITMAP hOverlay = static_cast<HBITMAP>(LoadImageW(nullptr, L"guitar1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));
        HBITMAP hBackground = static_cast<HBITMAP>(LoadImageW(nullptr, L"cMaj.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));

        // Create compatible DCs
        BITMAP bmBackground, bmOverlay;
        HDC hdcMemBackground = CreateCompatibleDC(hdc);
        HDC hdcMemOverlay = CreateCompatibleDC(hdc);
        
        GetObjectW(hBackground, sizeof(bmBackground), &bmBackground);
        GetObjectW(hOverlay, sizeof(bmOverlay), &bmOverlay);
        // Select the bitmaps into the DCs
        SelectObject(hdcMemBackground, hBackground);
       SelectObject(hdcMemOverlay, hOverlay);

        // Get the dimensions of the bitmaps
      //  BITMAP bmBackground;
       // GetObject(hBackground, sizeof(bmBackground), &bmBackground);
      

        // Create a destination DC for displaying the final image
        HDC hdcDest = CreateCompatibleDC(hdc);
        HDC hdcDestGO = CreateCompatibleDC(hdc);
        HBITMAP hFinalBitmap = CreateCompatibleBitmap(hdc, bmBackground.bmWidth, bmBackground.bmHeight);
        HBITMAP hFinalBitmapGO = CreateCompatibleBitmap(hdc, bmOverlay.bmWidth, bmOverlay.bmHeight);
        SelectObject(hdcDest, hFinalBitmap);
   
       // HBITMAP hFinalBitmapGO = CreateCompatibleBitmap(hdc, bmOverlay.bmWidth, bmOverlay.bmHeight);
        SelectObject(hdcDestGO, hFinalBitmapGO);

        // Draw the background bitmap
       // BitBlt(hdcDestGO, 0, 0, bmOverlay.bmWidth, bmOverlay.bmHeight, hdcMemBackground, 0, 0, SRCCOPY);
        BitBlt(hdcDest, 0, 0, bmBackground.bmWidth, bmBackground.bmHeight, hdcMemBackground, 0, 0, SRCCOPY);
        BitBlt(hdcDestGO, 0, 0, bmOverlay.bmWidth, bmOverlay.bmHeight, hdcMemOverlay, 0, 0, SRCCOPY);
        BitBlt(hdcDestGO, 0, 0, bmOverlay.bmWidth, bmOverlay.bmHeight, hdcMemOverlay, 0, 0, SRCCOPY);
        // Inside your game loop


        // Draw the overlay bitmap on top of the background

        // Display the final image
       // HWND hWnd = CreateWindowEx(0, L"STATIC", nullptr, WS_VISIBLE | WS_POPUP, 0, 0, bmBackground.bmWidth, bmBackground.bmHeight, nullptr, nullptr, hInst, nullptr);
        HDC hwndDC = GetDC(hwnd);
        HDC hwndDCGO = GetDC(hwnd);
        BitBlt(hwndDC, 0, 550, bmBackground.bmWidth, bmBackground.bmHeight, hdcDest, 0, 0, SRCCOPY);
        BitBlt(hwndDCGO, 0, 0, bmOverlay.bmWidth, bmOverlay.bmHeight, hdcDestGO, 0, 0, SRCCOPY);
        BitBlt(hwndDCGO, 0, 280, bmOverlay.bmWidth, bmOverlay.bmHeight, hdcDestGO, 0, 0, SRCCOPY);
        // Clean up
        DeleteDC(hdcDest);
        DeleteDC(hdcDestGO);
        DeleteObject(hFinalBitmap);
        DeleteObject(hFinalBitmapGO);
        DeleteDC(hdcMemBackground);
        DeleteDC(hdcMemOverlay);
        DeleteObject(hBackground);
        DeleteObject(hOverlay);


        ReleaseDC(hwnd, hwndDC);
        ReleaseDC(hwnd, hwndDCGO);
        ReleaseDC(nullptr, hdc);
        EndPaint(hwnd, &ps);

    }
    break;

    case WM_COMMAND:
    {
        switch (LOWORD(wParam))
        {
        case IDM_C_MAJOR:
        {
            HMENU hSubMenu = GetSubMenu(GetMenu(hwnd), 0);
            MENUITEMINFO mii = { 0 };
            mii.cbSize = sizeof(MENUITEMINFO);
            mii.fMask = MIIM_STATE;
            GetMenuItemInfo(hSubMenu, IDM_C_MAJOR, FALSE, &mii);
            mii.fState = (mii.fState & MFS_CHECKED) ? MFS_UNCHECKED : MFS_CHECKED;
            SetMenuItemInfo(hSubMenu, IDM_C_MAJOR, FALSE, &mii);
            break;
        }
        case IDOK:
        {
            std::vector<std::vector<int>> inputFretNumbers(6, std::vector<int>(16, -1));

            for (int fret = 0; fret < 16; ++fret)
            {
                WCHAR buffer[256];
                GetWindowText(hwndInput[0][fret], buffer, 256);
                std::wstring inputStr(buffer);

                if (!ValidateFretInput(inputStr))
                {
                    MessageBox(hwnd, L"Invalid input detected. Please enter fret numbers between 0 and 24.", L"Input Error", MB_ICONERROR);
                    return 0;
                }

                inputFretNumbers[0][fret] = inputStr.empty() ? -1 : _wtoi(buffer);
            }

            for (int fret = 0; fret < 16; ++fret)
            {
                WCHAR buffer[256];
                GetWindowText(hwndInput[1][fret], buffer, 256);
                std::wstring inputStr(buffer);

                if (!ValidateFretInput(inputStr))
                {
                    MessageBox(hwnd, L"Invalid input detected. Please enter fret numbers between 0 and 24.", L"Input Error", MB_ICONERROR);
                    return 0;
                }

                inputFretNumbers[1][fret] = inputStr.empty() ? -1 : _wtoi(buffer);
            }

            for (int fret = 0; fret < 16; ++fret)
            {
                WCHAR buffer[256];
                GetWindowText(hwndInput[2][fret], buffer, 256);
                std::wstring inputStr(buffer);

                if (!ValidateFretInput(inputStr))
                {
                    MessageBox(hwnd, L"Invalid input detected. Please enter fret numbers between 0 and 24.", L"Input Error", MB_ICONERROR);
                    return 0;
                }

                inputFretNumbers[2][fret] = inputStr.empty() ? -1 : _wtoi(buffer);
            }

            for (int fret = 0; fret < 16; ++fret)
            {
                WCHAR buffer[256];
                GetWindowText(hwndInput[3][fret], buffer, 256);
                std::wstring inputStr(buffer);

                if (!ValidateFretInput(inputStr))
                {
                    MessageBox(hwnd, L"Invalid input detected. Please enter fret numbers between 0 and 24.", L"Input Error", MB_ICONERROR);
                    return 0;
                }

                inputFretNumbers[3][fret] = inputStr.empty() ? -1 : _wtoi(buffer);
            }

            for (int fret = 0; fret < 16; ++fret)
            {
                WCHAR buffer[256];
                GetWindowText(hwndInput[4][fret], buffer, 256);
                std::wstring inputStr(buffer);

                if (!ValidateFretInput(inputStr))
                {
                    MessageBox(hwnd, L"Invalid input detected. Please enter fret numbers between 0 and 24.", L"Input Error", MB_ICONERROR);
                    return 0;
                }

                inputFretNumbers[4][fret] = inputStr.empty() ? -1 : _wtoi(buffer);
            }


            for (int fret = 0; fret < 16; ++fret)
            {
                WCHAR buffer[256];
                GetWindowText(hwndInput[5][fret], buffer, 256);
                std::wstring inputStr(buffer);

                if (!ValidateFretInput(inputStr))
                {
                    MessageBox(hwnd, L"Invalid input detected. Please enter fret numbers between 0 and 24.", L"Input Error", MB_ICONERROR);
                    return 0;
                }

                inputFretNumbers[5][fret] = inputStr.empty() ? -1 : _wtoi(buffer);
            }

            std::vector<std::vector<int>> harmony = CalculateHarmony(inputFretNumbers);

            for (int fret = 0; fret < 16; ++fret)
            {
                if (harmony[0][fret] >= 0)
                {
                    WCHAR buffer[10];
                    wsprintf(buffer, L"%d", harmony[0][fret]);
                    SetWindowText(hwndOutput[1][fret], buffer);
                }
                else
                {
                    SetWindowText(hwndOutput[1][fret], L"");
                }
            }

            for (int fret = 0; fret < 16; ++fret)
            {
                if (harmony[1][fret] >= 0)
                {
                    WCHAR buffer[10];
                    wsprintf(buffer, L"%d", harmony[1][fret]);
                    SetWindowText(hwndOutput[2][fret], buffer);
                }
                else
                {
                    SetWindowText(hwndOutput[2][fret], L"");
                }
            }


            for (int fret = 0; fret < 16; ++fret)
            {
                if (harmony[2][fret] >= 0)
                {
                    WCHAR buffer[10];
                    wsprintf(buffer, L"%d", harmony[2][fret]);
                    SetWindowText(hwndOutput[3][fret], buffer);
                }
                else
                {
                    SetWindowText(hwndOutput[3][fret], L"");
                }
            }


            for (int fret = 0; fret < 16; ++fret)
            {
                if (harmony[3][fret] >= 0)
                {
                    WCHAR buffer[10];
                    wsprintf(buffer, L"%d", harmony[3][fret]);
                    SetWindowText(hwndOutput[4][fret], buffer);
                }
                else
                {
                    SetWindowText(hwndOutput[4][fret], L"");
                }
            }


            for (int fret = 0; fret < 16; ++fret)
            {
                if (harmony[4][fret] >= 0)
                {
                    WCHAR buffer[10];
                    wsprintf(buffer, L"%d", harmony[4][fret]);
                    SetWindowText(hwndOutput[5][fret], buffer);
                }
                else if (harmony[5][fret] >= 0)
                {
                    WCHAR buffer[10];
                    wsprintf(buffer, L"%d", harmony[5][fret]);
                    SetWindowText(hwndOutput[5][fret], buffer);
                }
                else
                {
                    SetWindowText(hwndOutput[5][fret], L"");
                }
            }


            break;
        }

        case IDplay1:
        {
            
            WCHAR buffer[256];

            for (int fret = 0; fret < 16; ++fret)
            {
                system2->update();  // Move the update outside of the loop to ensure proper system handling

                for (int stringIndex = 0; stringIndex < 6; ++stringIndex)
                {
                    GetWindowText(hwndInput[stringIndex][fret], buffer, 256);
                    std::wstring inputStr(buffer);

                    if (!inputStr.empty())
                    {
                        int interval = _wtoi(buffer);
                        pitchMultiplier = std::pow(2.0f, static_cast<float>(interval) / 12.0f);

                        // Adjust the note based on the current string
                        FMOD::Sound* currentNote;
                        switch (stringIndex)
                        {
                        case 0: currentNote = notehE; break;
                        case 1: currentNote = notehB; break;
                        case 2: currentNote = notehG; break;
                        case 3: currentNote = notehD; break;
                        case 4: currentNote = notehA; break;
                        case 5: currentNote = noteLE; break;
                        default: currentNote = noteLE;  break;
                            // Default to high E if an invalid stringIndex is provided
                        }

                        system2->playSound(currentNote, nullptr, false, &channel1);
                        channel1->setPitch(pitchMultiplier);

                        Sleep(500);  // Adjust the delay as needed
                    }
                }
            }



            break;
        }

        case IDplay3:
        {
            /*
            WCHAR buffer[256], buffer2[256];
            unsigned long long dspclock_start, dspclock_end;
     

            // Initial DSP Clock retrieval
            unsigned long long initialDSPClock, currentDSPClock;
            system2->getMasterChannelGroup(&masterGroup);
            masterGroup->getDSPClock(&currentDSPClock, &initialDSPClock);

            unsigned long long delayTicksPerSecond = 48000; // 48 kHz
            unsigned long long noteDurationTicks = delayTicksPerSecond * 1; // 1 second note duration

            for (int fret = 0; fret < 16; ++fret)
            {
                for (int stringIndex = 0; stringIndex < 6; ++stringIndex)
                {
                    dspclock_start = initialDSPClock + (fret * 6 + stringIndex) * noteDurationTicks;
                    dspclock_end = dspclock_start + noteDurationTicks;

                    // Schedule and play the first set of notes
                    GetWindowText(hwndInput[stringIndex][fret], buffer, 256);
                    if (!std::wstring(buffer).empty())
                    {
                        switch (stringIndex)
                        {
                        case 0: currentNote = notehE; break;
                        case 1: currentNote = notehB; break;
                        case 2: currentNote = notehG; break;
                        case 3: currentNote = notehD; break;
                        case 4: currentNote = notehA; break;
                        case 5: currentNote = noteLE; break;
                        default: currentNote = noteLE;  break;
                            // Default to high E if an invalid stringIndex is provided
                        }
                        system2->playSound(currentNote, nullptr, true, &channel1);
                        channel1->setPitch(pitchMultiplier);
                        channel1->setDelay( dspclock_start, dspclock_end, true);
                        channel1->setPaused(false);
                    }

                    // Schedule and play the second set of notes
                    GetWindowText(hwndOutput[stringIndex][fret], buffer2, 256);
                    if (!std::wstring(buffer2).empty())
                    {
                        switch (stringIndex)
                        {
                        case 0: currentNote2 = notehE; break;
                        case 1: currentNote2 = notehB; break;
                        case 2: currentNote2 = notehG; break;
                        case 3: currentNote2 = notehD; break;
                        case 4: currentNote2 = notehA; break;
                        case 5: currentNote2 = noteLE; break;
                        default: currentNote2 = noteLE;  break;
                            // Default to high E if an invalid stringIndex is provided
                        }
                        system2->playSound(currentNote2, nullptr, true, &channel2);
                        channel2->setPitch(pitchMultiplier2);
                        channel2->setDelay(dspclock_start, dspclock_end, true);
                        channel2->setPaused(false);
                    }
                }
            }
            */

            unsigned long long dspClockStart, dspClockEnd;
            unsigned long long delayBetweenPlays = 48000 * 2; // 2 seconds delay in ticks, assuming a sample rate of 48 kHz
            unsigned long long playDuration = 48000; // Duration of the sound to play, assuming it lasts for 1 second

            // Retrieve the initial DSP clock values
            unsigned long long initialDSPClock, currentDSPClock;
            system2->getMasterChannelGroup(&masterGroup);
            masterGroup->getDSPClock(&currentDSPClock, &initialDSPClock);

            // Play the sound 5 times every 2 seconds
            for (int i = 0; i < 5; ++i)
            {
                // Calculate the DSP clock start time for the current iteration
                dspClockStart = initialDSPClock + i * delayBetweenPlays;

                // Calculate the end time, assuming the note plays for its entire duration
                dspClockEnd = dspClockStart + playDuration;

               // system2->update();
                FMOD_RESULT result = system2->playSound(notehE, nullptr, true, &channel1);
               channel1->setPitch(pitchMultiplier);
                FMOD_RESULT result2 = system2->playSound(notehB, nullptr, true, &channel2);
               // system2->update();
            //   channel2->setPitch(pitchMultiplier2);
              // system2->update();
                if (result == FMOD_OK && result2 == FMOD_OK) {
                    // Set the channel to start and end at the specific times calculated
                    channel1->setDelay(dspClockStart, dspClockEnd, false);
                    channel2->setDelay(dspClockStart, dspClockEnd, false);
                    // Unpause the channel to start playing
                    channel1->setPaused(false);
                   
                    channel2->setPaused(false);
                }
                else {
                    // Handle error
                    std::cerr << "Failed to play sound: " << result << std::endl;
                }

                // Note: In a real application, you would not usually use a loop like this to schedule future plays
                // because it assumes the play duration and does not dynamically adjust for the actual duration of the sound.
                // Additionally, FMOD manages timing and playback internally, and looping like this without delays or
                // synchronization primitives can lead to unpredictable results.
            }

            // Update FMOD system regularly to process sound playback
        
            break;
        }





        case IDplay2:
        {
            WCHAR buffer[256];

            for (int fret = 0; fret < 16; ++fret)
            {
                system2->update();  // Move the update outside of the loop to ensure proper system handling

                for (int stringIndex = 0; stringIndex < 6; ++stringIndex)
                {
                    GetWindowText(hwndOutput[stringIndex][fret], buffer, 256);
                    std::wstring inputStr(buffer);

                    if (!inputStr.empty())
                    {
                        int interval = _wtoi(buffer);
                        pitchMultiplier = std::pow(2.0f, static_cast<float>(interval) / 12.0f);

                        // Adjust the note based on the current string
                        FMOD::Sound* currentNote;
                        switch (stringIndex)
                        {
                        case 0: currentNote = notehE; break;
                        case 1: currentNote = notehB; break;
                        case 2: currentNote = notehG; break;
                        case 3: currentNote = notehD; break;
                        case 4: currentNote = notehA; break;
                        case 5: currentNote = noteLE; break;
                        default: currentNote = noteLE;  break;
                            // Default to high E if an invalid stringIndex is provided
                        }

                        system2->playSound(currentNote, nullptr, false, &channel1);
                        channel1->setPitch(pitchMultiplier);

                        Sleep(500);  // Adjust the delay as needed
                    }
                }
            }
        }
        }
            break;
        }

 


        

   
    /*

    case WM_TIMER:
    {
        if (wParam == PLAYBACK_TIMER_ID && isPlaying)
        {
            if (currentFret < 16)
            {
                WCHAR bufferE[256], bufferB[256];

                GetWindowText(hwndInput[0][currentFret], bufferE, 256);
                GetWindowText(hwndOutput[bString][currentFret], bufferB, 256);

                if (std::wstring(bufferE) != L"")
                {
                    int intervalE = _wtoi(bufferE);
                    float pitchMultiplierE = std::pow(2.0f, static_cast<float>(intervalE) / 12.0f);
                    system2->playSound(notehE, nullptr, false, &channel1);
                    channel1->setPitch(pitchMultiplierE);
                }

                if (std::wstring(bufferB) != L"")
                {
                    int intervalB = _wtoi(bufferB);
                    float pitchMultiplierB = std::pow(2.0f, static_cast<float>(intervalB) / 12.0f);
                    system2->playSound(notehB, nullptr, false, &channel2);
                    channel2->setPitch(pitchMultiplierB);
                }

                currentFret++;
            }
            else
            {
                isPlaying = false;
                KillTimer(hwnd, PLAYBACK_TIMER_ID);
            }
        }
        break;
    }
    */
    case WM_DESTROY:
    {
        if (masterGroup) {
            masterGroup->release();
        }
     

        notehE->release();
        notehB->release();
        notehG->release();
        notehD->release();
        notehA->release();
        noteLE->release();
        system2->close();
        system2->release();
        PostQuitMessage(0);
        break;
    }

    default:
    {
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    }
    return 0;
}


// ... [Rest of your code]

// ... [Earlier parts of your code, including global variables and function definitions]

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{
    // Register window class
    WNDCLASSEX wc = {};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = L"ScaleHarmonyApp";

    if (!RegisterClassEx(&wc)) {
        MessageBox(nullptr, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
    hInst = hInstance;
    // Create main window
    HWND hwnd = CreateWindowEx(
        0,
        L"ScaleHarmonyApp",
        L"Scale Harmony Calculator",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 900,
        nullptr, nullptr, hInstance, nullptr
    );

    if (hwnd == nullptr) {
        MessageBox(nullptr, L"Window Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Show and update the main window
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Initialize the fretboard
  
    // Create the menu
    HMENU hMenu = CreateMenu();
    HMENU hSubMenu = CreatePopupMenu();

    // Add the "Key" menu item and its submenu
    AppendMenu(hMenu, MF_STRING | MF_POPUP, reinterpret_cast<UINT_PTR>(hSubMenu), L"Key");
    AppendMenu(hSubMenu, MF_STRING | MF_CHECKED, IDM_C_MAJOR, L"C Major");


    // Set the menu to the window
    SetMenu(hwnd, hMenu);

    // Message loop
    MSG msg = {};
    while (GetMessage(&msg, nullptr, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return static_cast<int>(msg.wParam);
}

The most likely cause of the issue you’re describing is to do with the channels. A single sound can be played by multiple channels, each at a different pitch, but a channel can only play one sound, which would be my guess as to what’s happening here.

That shouldn’t be an issue - here’s a small snippet that successfully pitch shifts two channels playing the same sound:

result = system->playSound(sound, nullptr, false, &channel1);
result = system->playSound(sound, nullptr, false, &channel2);
channel->setPitch(1.5);
channel2->setPitch(0.5);

Debugging your code falls outside of the scope of forum support, but I would recommend looking into a couple of things:

  • Simplify your code as much as possible and see if the issue still reproduces - i.e. comment out the setDelay calls and the for loop and just play the sounds a single time, make sure nowhere else in the code is interfering with the channels after they’re set to play sounds, etc.
  • Are you accidentally playing both sounds on the same channel? Have channel1 and channel2 ended up as the same pointer somehow?

I can pitch shift 2 sounds like you showed in your code but the problem that each guitar has 16 notes its got to play .the first note works correctly but then after that u can only here the 1 channel . I want to play all 16 notes from guitar 1 with its maching note in guitar 2. Im thinking of prebaking all the notes so I dont have to use pitch shift and see if that solves the problem but i’m still working on the system.

Please correct me if I’m minsunderstanding - as previously mentioned, a channel can only play one sound at a time. If my snippet works for you, it’s likely a polyphony issue. If you require polyphony, I would recommend doing one of the following things:

  • Create one channel for each note a guitar needs to play i.e. 16 channels, one for each note. This will give you polyphony for the guitar, but you’ll only be able to play one instance of a given note at once
  • Create a new channel for each note a guitar plays and manage them accordingly. This gives you polyphony of the same note as well, but will require you to implement some kind of system to track which channels are currently playing