2017-04-17 34 views
0

Visual Studio 2005を使用してゲームを開発しています(コンピュータの中にはWindows 2000を実行しているものもありますが、これが実行される最新のバージョンで、これを新しいバージョンに簡単に変換できません) 。C++の非同期スレッド

私たちの音楽作曲家はすでにシステムをテストするためにいくつかの短いトラックを書きましたが、問題が発生しました: 音楽やサウンドエフェクトを再生中にゲームがフリーズします。

これは特にSFXにとって大きな問題ではありませんが、音楽はバックグラウンドで実行する必要があるため、非常に大きな問題です。

ループで指定したトラックを再生するために、バックグラウンドで2番目のスレッドまたはプロセスを作成する可能性がありますが、検索すると、データが必要なため、これでうまくいくものは見つかりません2つのプロセス間で(片方向ではあるが)転送する。

私はそれを見て、再生するトラック番号を含むメインプログラムから音楽プロセスにコマンドを渡すことができるはずです - これはかなり簡単なはずですが、最近C++に移動して、現在、それは非常に経験豊かです。

ありがとうございます。

P.S.古いソフトウェアを使用することについてコメントしてはいけません。私たちはこれを楽しいものとして行い、まったくお金を入れるつもりはありません。

編集明快にするために、私たちはすべてWindowsを実行しており、これを他のプラットフォームに移植する予定はありません - Visual Studio 2005を実行していますが、Visual Studio 2008または2010 Ultimateで、適切なディスクとソフトウェアを入手することができます。

音楽はビープ音()を使用して行われます。コマンドは、標準のWindowsヘッダファイル(windows.h)に組み込まれています。

バックグラウンドミュージックを可能にするために、メインプログラムと並行して2次プロセスを実行したいと考えています。

2つのプロセス間のデータ転送が大きすぎると判明した場合、開始時に開始変数をトラック番号として渡して、終了時に単純に終了させることができますか?

+0

はWIN32の[マルチスレッド]を記述するMSDN上のリソース(https://msdn.microsoft.com/en-us/library/y6h8hye8(V = vs.80).aspxの)機能をがあります。 ''ライブラリのような新しいC++機能にアクセスすることができなければ、あなたはWIN32システムコールを使って手動で多くのことをする必要があります。 – lcs

+0

トラック番号のみを転送する場合は、アトムint 'trackNum' varを使用し、サウンドスレッドがトラックの最後に到達したときにそれを読み取らせ、ネスト1を選択する必要がある(または同じものを繰り返す) )。それを止める必要がある場合は、「-1」は「今すぐ停止してイベントを待つ」という意味にすることができます。 – ThingyWotsit

+0

はい、どうしたら新しいスレッドを作成してこれを許可しますか?簡単な例を教えてください。 – FAMICOMASTER

答えて

0

Visual Studioの場合、volatileとして宣言された変数にはメモリーフェンス操作が含まれます(このオプションがオフになっていない場合は、デフォルトでオン)ので、スレッド間で使用できます。このコードでは、音楽トラックを再生するための揮発性変数を使用することができます。私は以下のCコード例を含めました。

私は、音楽を再生している間は、Beep()はCPUに束縛されないことを前提としています(Windows XPのようではありません)。

より正確なタイミングを得るために、ticker frequencyを64hz(15.625ms)から1000hz(1ms)に増やすためにtimeBeginPeriod()を使用できます。 Windows XPとおそらくWindows 2000の場合、Sleep()と私の推測Beep()は128ティックごとに3つの余分な実際のティックを追加して1000hzティッカーをエミュレートするのに対して、timeBeginPeriod(1)は1024hzで実際にティッカーを実行させます125ミリ秒の境界線上で立ち上がります。これは、Sleep(1)が(42,84、および125コールで)時々約2msまでかかる可能性があることを意味します。

注 - 最終的に通信するハードウェアが不足しているため、Windows VistaおよびWindows XP 64ビット版ではビープ音はサポートされませんでした。 Windows 7では、ビープ音がセッションのデフォルトのサウンドデバイスに送信されるように書き換えられました。これは通常、ターミナルサービスで実行されている場合を除いてサウンドカードです。この場合、ビープ音はクライアントで表示されます。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms679277(v=vs.85).aspx

例マルチスレッド "ビープ" コード。このコードは、PCスピーカーを使用してWindows XPで正常に動作します。 Windows 7では、サウンドカードを使用しており、音符の間には何らかの無音があります。

/*----------------------------------------------------------------------*/ 
/*  mtbeep.c  multi-thread beep demo       */ 
/*----------------------------------------------------------------------*/ 
#include <windows.h> 
/* include winmm.lib for timeBeginPeriod */ 
#pragma comment(lib, "winmm.lib") 

#define TRACK0 0 
#define TRACK1 1 
#define TRACK2 2 
#define TRACKX 3      /* exit thread 1 if trackx */ 

typedef struct { 
    DWORD dwFreq; 
    DWORD dwDuration; 
}NOTE; 

/*----------------------------------------------------------------------*/ 
/*  data               */ 
/*----------------------------------------------------------------------*/ 
static HANDLE htT1;     /* thread 1 handle */ 
static DWORD dwThreadT1;    /* thread id's (not used) */ 

static volatile DWORD dwTrack;   /* beep track to play */ 

/* songs */ 
static NOTE  anTrack0[4] = {300, 500, 450, 500, 600, 500, 0, 0}; 
static NOTE  anTrack1[4] = { 0, 250}; 
static NOTE  anTrack2[4] = {400, 500, 300, 500, 200, 500, 0, 0}; 
static NOTE  anTrackx[4] = {0, 0}; 

/*----------------------------------------------------------------------*/ 
/*  code               */ 
/*----------------------------------------------------------------------*/ 
static DWORD WINAPI Thread0(LPVOID); 
static DWORD WINAPI Thread1(LPVOID); 
/*----------------------------------------------------------------------*/ 
/*  main               */ 
/*----------------------------------------------------------------------*/ 
DWORD main(DWORD argc, BYTE **argv) 
{ 
    timeBeginPeriod(1);     /* set period to 1ms */ 
    Sleep(128);       /* wait for it to stabilize */ 

    /* create thread */ 
    htT1 = CreateThread(NULL, 0, Thread1, 0, 0, &dwThreadT1); 
    if(!htT1){ 
     /* createthread failed */ 
     goto exit0;} 
    Thread0((LPVOID)NULL);    /* start Thread 0 */ 
exit0: 
    if(htT1){       /* close thread */ 
     dwTrack = TRACKX; 
     WaitForSingleObject(htT1, INFINITE); 
     CloseHandle(htT1);} 
    timeEndPeriod(1);     /* restore period */ 
    return(0); 
} 

/*----------------------------------------------------------------------*/ 
/*  Thread0               */ 
/*----------------------------------------------------------------------*/ 
static DWORD WINAPI Thread0(LPVOID lpvoid) 
{ 
int i; 
    for(i = 0; i < 4; i++){ 
     dwTrack = i%3; 
     Sleep(5000); 
    } 
    return 0; 
} 

/*----------------------------------------------------------------------*/ 
/*  Thread1   beep thread          */ 
/*----------------------------------------------------------------------*/ 
static DWORD WINAPI Thread1(LPVOID lpvoid) 
{ 
NOTE *apTrack[4] = {anTrack0, anTrack1, anTrack2, anTrackx}; 
NOTE *pTrack = anTrack0;    /* ptr to array of notes */ 
DWORD cTrack = TRACKX;     /* current track */ 
int iNote = 0;       /* note index */ 

    while(dwTrack != TRACKX){   /* play a note loop */ 
     if(cTrack != dwTrack){   /* if song changed */ 
      iNote = 0;     /* start at first note */ 
      cTrack = dwTrack;   /* of next song */ 
      pTrack = apTrack[cTrack]; 
     } 
     if(!pTrack[iNote].dwDuration) /* if end of song */ 
      iNote = 0;     /* reset note index */ 
     if(pTrack[iNote].dwFreq)  /* if note play it */ 
      Beep(pTrack[iNote].dwFreq, pTrack[iNote].dwDuration); 
     else       /* else silence */ 
      Sleep(pTrack[iNote].dwDuration); 
     iNote++; 
    } 
    return(0); 
} 
+0

これは非常に良いですが、そのようなソリューションをどのように実装するのかはわかりません。 これはこれまでのところ最高の答えだったかもしれませんが、これは非常に緑色なので、これが何であるかはわかりません。 タイミングは特に問題ではなく、プロセス(私たちの考え方)は互いに並列に実行され、コマンドが送信された場合を除いては全く同期して実行する必要はありません。 – FAMICOMASTER

+0

@FAMICOMASTER - ビープ音()を使って "曲"を演奏する例を示すために答えを変更しました。 – rcgldr

+0

まだ試していないが、これはうまくいくようだ。ありがとうございました! – FAMICOMASTER

関連する問題