Sign in to follow this  

How to loop music?

This topic is 4338 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have taken an example from the book Programming Role Playing Games With DirectX (2nd Edition) and have not yet been anle to fully integrate looping music into my project. I have the full source code and .bmp, .mp3 files here (right-click). Any help would be appreciated. I'll also post my code here:
Music is played first (need to synch with billboard)
// Microsoft Developer Studio generated include file.
// Resource files no longer necessary
#define IDD_ENUM                        101
#define IDD_MP3Play                     101
#define IDC_ADAPTERS                    1000
#define IDC_DEVICES                     1000
#define IDC_OUTPUT                      1000
#define IDC_MODES                       1001
#define IDC_STATIC1                     1003

// Next default values for new objects
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1005
#define _APS_NEXT_SYMED_VALUE           101

// Include files
#include <windows.h>
#include <stdio.h>
#include "d3d9.h"
#include "d3dx9.h"

//Music include
#include <dshow.h>

// Window handles, class and caption text
HWND          g_hWnd;
HINSTANCE     g_hInst;
static char   g_szClass[]   = "BillboardClass";
static char   g_szCaption[] = "Billboard Demo by teh_pwnerer";

// The Direct3D and Device object
IDirect3D9       *g_pD3D       = NULL;
IDirect3DDevice9 *g_pD3DDevice = NULL;

// DirectShow components
IGraphBuilder *g_pDSGraphBuilder = NULL;
IMediaControl *g_pDSMediaControl = NULL;
IMediaEvent   *g_pDSMediaEvent   = NULL;

// The 3D vertex format and descriptor
typedef struct {
  FLOAT x, y, z;   // 3D coordinates
  FLOAT u, v;      // Texture coordinates
} s3DVertex;
#define FVF3D (D3DFVF_XYZ | D3DFVF_TEX1)

// The billboard vertex buffer and texture
IDirect3DVertexBuffer9 *g_pBillboardVB      = NULL;
IDirect3DTexture9      *g_pBillboardTexture = NULL;

// The floor vertex buffer and texture
IDirect3DVertexBuffer9 *g_pFloorVB      = NULL;
IDirect3DTexture9      *g_pFloorTexture = NULL;

// Function prototypes
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);
long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

BOOL DoInit();
BOOL DoShutdown();
BOOL DoFrame();
BOOL SetupMeshes();

// Application prototypes ///////////////////////
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);
long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

BOOL PlaySong(char *Filename);

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
  MSG        Msg;

  g_hInst = hInst;

  // Create the window class here and register it
  wcex.cbSize        = sizeof(wcex);         = CS_CLASSDC;
  wcex.lpfnWndProc   = WindowProc;
  wcex.cbClsExtra    = 0;
  wcex.cbWndExtra    = 0;
  wcex.hInstance     = hInst;
  wcex.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = NULL;
  wcex.lpszMenuName  = NULL;
  wcex.lpszClassName = g_szClass;
  wcex.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    return FALSE;


  // Initialize COM

  // Register window class         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = WindowProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = DLGWINDOWEXTRA;
  wc.hInstance     = hInst;
  wc.hIcon         = LoadIcon(hInst, IDI_APPLICATION);
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = g_szClass;

  // Create the dialog box window and show it
  g_hWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MP3Play), 0, NULL);
  ShowWindow(g_hWnd, nCmdShow);

  // Create the Main Window
  g_hWnd = CreateWindow(g_szClass, g_szCaption,
        0, 0, 1024, 768,
        NULL, NULL,
        hInst, NULL );
    return FALSE;
  ShowWindow(g_hWnd, SW_NORMAL);

  // Initialize and configure DirectShow
  if(FAILED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&g_pDSGraphBuilder))) {
    MessageBox(NULL, "Unable to create DirectShow Graph Builder object", "Error", MB_OK);
    return FALSE;

  // Query for the media control and event objects
  g_pDSGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&g_pDSMediaControl);
  g_pDSGraphBuilder->QueryInterface(IID_IMediaEvent,   (void**)&g_pDSMediaEvent);
  // Play some music
  PlaySong("Doom 3 Intro.mp3");

  // Clean up
  UnregisterClass(g_szClass, hInst);

  // Release COM system

  // Run init function and return on error
  if(DoInit() == FALSE)
    return FALSE;

  // Start message pump, waiting for signal to quit
  ZeroMemory(&Msg, sizeof(MSG));
  while(Msg.message != WM_QUIT) {
    if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
    if(DoFrame() == FALSE)

  // Run shutdown function
  UnregisterClass(g_szClass, hInst);

  return Msg.wParam;

long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  switch(uMsg) {
    case WM_DESTROY:
      return 0;

  return DefWindowProc(hWnd, uMsg, wParam, lParam);
BOOL PlaySong(char *Filename)
  // Convert filename to wide-character string
  WCHAR wFilename[MAX_PATH];
  mbstowcs(wFilename, Filename, MAX_PATH);

  // Render the file
  g_pDSGraphBuilder->RenderFile(wFilename, NULL);

  // Play the file

  return TRUE;
BOOL DoInit()
  D3DDISPLAYMODE        d3ddm;
  D3DXMATRIX            matView, matProj;

  // Do a windowed mode initialization of Direct3D
  if((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
    return FALSE;
  if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
    return FALSE;
  ZeroMemory(&d3dpp, sizeof(d3dpp));
  d3dpp.Windowed = TRUE;
  d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  d3dpp.BackBufferFormat = d3ddm.Format;
  d3dpp.EnableAutoDepthStencil = TRUE;
  d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

                                  &d3dpp, &g_pD3DDevice)))
    return FALSE;

  // Set the render states
  g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
  g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  g_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x01);

  // Create and set the projection transformation
  D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f);
  g_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);

  // Create the meshes

  return TRUE;

BOOL DoShutdown()
  // Release textures and vertex buffers
  if(g_pBillboardTexture != NULL)

  if(g_pBillboardVB != NULL)

  if(g_pFloorTexture != NULL)

  if(g_pFloorVB != NULL)

  // Release device and 3D objects
  if(g_pD3DDevice != NULL)

  if(g_pD3D != NULL)

  return TRUE;

BOOL DoFrame()
  D3DXMATRIX matView, matWorld;
  float      Angle;
  short      i, j;

  // Clear device backbuffer
  g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0,64,128,255), 1.0f, 0);

  // Update the view position
  Angle = (float)timeGetTime() / 2000.0f;
  D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3((float)cos(Angle) * 400.0f, 150.0f, (float)sin(Angle) * 200.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);

  if(SUCCEEDED(g_pD3DDevice->BeginScene())) {
    // Draw the floor
    g_pD3DDevice->SetStreamSource(0, g_pFloorVB, 0, sizeof(s3DVertex));
    g_pD3DDevice->SetTexture(0, g_pFloorTexture);
    g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
    g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

    // Draw the billboards
    g_pD3DDevice->SetStreamSource(0, g_pBillboardVB, 0, sizeof(s3DVertex));
    g_pD3DDevice->SetTexture(0, g_pBillboardTexture);

    g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
    D3DXMatrixTranspose(&matWorld, &matView);
    for(i=0;i<3;i++) {
      for(j=0;j<3;j++) {
        matWorld._41 = (float)i *  80.0f - 80.0f;
        matWorld._42 = 0.0f;
        matWorld._43 = (float)j *  80.0f - 80.0f;

        g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
        g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
    g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

    // Clear the texture usage
    g_pD3DDevice->SetTexture(0, NULL);

    // End the scene

  // Display the scene
  g_pD3DDevice->Present(NULL, NULL, NULL, NULL);

  return TRUE;

BOOL SetupMeshes()
  BYTE *Ptr;
  s3DVertex BillboardVerts[4] = {
      { -42.0f, 80.0f, 0.0f, 0.0f, 0.0f },
      {  40.0f, 80.0f, 0.0f, 1.0f, 0.0f },
      { -40.0f,  0.0f, 0.0f, 0.0f, 1.0f },
      {  40.0f,  0.0f, 0.0f, 1.0f, 1.0f }

  s3DVertex FloorVerts[4] = {
      { -100.0f, 0.0f,  100.0f, 0.0f, 0.0f },
      {  100.0f, 0.0f,  100.0f, 1.0f, 0.0f },
      { -100.0f, 0.0f, -100.0f, 0.0f, 1.0f },
      {  100.0f, 0.0f, -100.0f, 1.0f, 1.0f }

  // Create vertex buffers and stuff in data
  // Billboard
  if(FAILED(g_pD3DDevice->CreateVertexBuffer(                             sizeof(BillboardVerts), 0, FVF3D,                             D3DPOOL_DEFAULT, &g_pBillboardVB, NULL)))
    return FALSE;
  if(FAILED(g_pBillboardVB->Lock(0,0, (void**)&Ptr, 0)))
    return FALSE;
  memcpy(Ptr, BillboardVerts, sizeof(BillboardVerts));

   // Floor
  if(FAILED(g_pD3DDevice->CreateVertexBuffer(                             sizeof(FloorVerts), 0, FVF3D,                                 D3DPOOL_DEFAULT, &g_pFloorVB, NULL)))
    return FALSE;
  if(FAILED(g_pFloorVB->Lock(0,0, (void**)&Ptr, 0)))
    return FALSE;
  memcpy(Ptr, FloorVerts, sizeof(FloorVerts));

  // Get textures 
  D3DXCreateTextureFromFile(g_pD3DDevice, "Floor.bmp", &g_pFloorTexture);
  D3DXCreateTextureFromFileEx(g_pD3DDevice, "Billboard.bmp", 
    D3DCOLOR_RGBA(0,0,0,255), NULL, NULL, &g_pBillboardTexture);

  return TRUE;

[Edited by - teh_programerer on January 28, 2006 2:40:22 PM]

Share this post

Link to post
Share on other sites
It looks like you are using DirectShow there. As I recall, I used the IMediaSeeking interface of DirectShow to continually poll the play position of the song as well as move the play position around. When it reached the end-loop-point I'd reset back to the begin-loop-point.

It's been a year or so and I don't have the code with me here to check, so I really can't be sure. It sounds right though. Hope this helps.

Share this post

Link to post
Share on other sites

This topic is 4338 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this