News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

How to play WAV/MP3-file from memory?

Started by Mikl__, March 02, 2022, 02:01:41 PM

Previous topic - Next topic

Mikl__

Hi, All!
PlaySound with SND_MEMORY is not suitable.
Preferably via mciwioOpen/mciwioPlay or any other options. . .
Thank you!

Greenhorn

Kole Feut un Nordenwind gift en krusen Büdel un en lütten Pint.

Mikl__

Hello, Greenhorn!
Thanks for the tip, no, I haven't tried it, now I'll read about this dll

LiaoMi

Hi Mikl,

; #########################################################################
;
;   This demo shows how to use the new bitmap button custom control in
;   MASM32 library. This control allows you to use any UP & DOWN bitmap
;   you like so you can use non rectangular shapes if you bother to
;   match the bitmap back colour to the colour of the client area.
;
;   These 2 bitmaps were created by "Novatrix" from New Zealand.
;
; #########################################################################

      .386
      .model flat, stdcall  ; 32 bit memory model
      option casemap :none  ; case sensitive

      include bmpbutns.inc  ; local includes for this file
      include \masm32\include\winmm.inc
     
      Include \masm32\macros\macros.asm

      includelib \masm32\lib\winmm.lib
; #########################################################################
; --------------------------------------------------------
   
   
        PlayMp3File PROTO :DWORD,:DWORD

; --------------------------------------------------------
.data


        Mp3DeviceID DD 0
        Mp3Device   DB "MPEGVideo",0

.data?   
.code

start:
      invoke GetModuleHandle, NULL
      mov hInstance, eax

      invoke GetCommandLine
      mov CommandLine, eax

      invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT
      invoke ExitProcess,eax

; #########################################################################

WinMain proc hInst     :DWORD,
             hPrevInst :DWORD,
             CmdLine   :DWORD,
             CmdShow   :DWORD

      ;====================
      ; Put LOCALs on stack
      ;====================

      LOCAL wc   :WNDCLASSEX
      LOCAL msg  :MSG
      LOCAL Wwd  :DWORD
      LOCAL Wht  :DWORD
      LOCAL Wtx  :DWORD
      LOCAL Wty  :DWORD

      ;==================================================
      ; Fill WNDCLASSEX structure with required variables
      ;==================================================

      invoke LoadIcon,hInst,500    ; icon ID
      mov hIcon, eax

      szText szClassName,"Project_Class"

      mov wc.cbSize,         sizeof WNDCLASSEX
      mov wc.style,          CS_BYTEALIGNWINDOW
      mov wc.lpfnWndProc,    offset WndProc
      mov wc.cbClsExtra,     NULL
      mov wc.cbWndExtra,     NULL
      m2m wc.hInstance,      hInst
      mov wc.hbrBackground,  COLOR_BTNFACE+1
      mov wc.lpszMenuName,   NULL
      mov wc.lpszClassName,  offset szClassName
      m2m wc.hIcon,          hIcon
        invoke LoadCursor,NULL,IDC_ARROW
      mov wc.hCursor,        eax
      m2m wc.hIconSm,        hIcon

      invoke RegisterClassEx, ADDR wc

      ;================================
      ; Centre window at following size
      ;================================

      mov Wwd, 300
      mov Wht, 255

      invoke GetSystemMetrics,SM_CXSCREEN
      invoke TopXY,Wwd,eax
      mov Wtx, eax

      invoke GetSystemMetrics,SM_CYSCREEN
      invoke TopXY,Wht,eax
      mov Wty, eax

      invoke CreateWindowEx,WS_EX_LEFT,
                            ADDR szClassName,
                            ADDR szDisplayName,
                            WS_OVERLAPPEDWINDOW,
                            Wtx,Wty,Wwd,Wht,
                            NULL,NULL,
                            hInst,NULL
      mov   hWnd,eax

      invoke LoadMenu,hInst,600  ; menu ID
      invoke SetMenu,hWnd,eax

      invoke ShowWindow,hWnd,SW_SHOWNORMAL
      invoke UpdateWindow,hWnd

      ;===================================
      ; Loop until PostQuitMessage is sent
      ;===================================

    StartLoop:
      invoke GetMessage,ADDR msg,NULL,0,0
      cmp eax, 0
      je ExitLoop
      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage,  ADDR msg
      jmp StartLoop
    ExitLoop:

      return msg.wParam

WinMain endp

; #########################################################################

WndProc proc hWin   :DWORD,
             uMsg   :DWORD,
             wParam :DWORD,
             lParam :DWORD

    LOCAL var    :DWORD
    LOCAL caW    :DWORD
    LOCAL caH    :DWORD
    LOCAL Rct    :RECT
    LOCAL hDC    :DWORD
    LOCAL hBmp1  :DWORD
    LOCAL hBmp2  :DWORD
    LOCAL Ps     :PAINTSTRUCT
    LOCAL buffer1[128]:BYTE  ; these are two spare buffers
    LOCAL buffer2[128]:BYTE  ; for text manipulation etc..

   .if uMsg == WM_CREATE
            szText msg2,"sample.mp3"
            Invoke PlayMp3File, hWin, Addr msg2


   .endif

    .if uMsg == WM_COMMAND
      .if wParam == 500
                    szText msg1,"Hi, you clicked the bitmap button"
                    invoke MessageBox,hWin,ADDR msg1,ADDR szDisplayName,MB_OK


      .endif

    ;======== menu commands ========
    .elseif uMsg == WM_CREATE
      ; ------------------------------------
      ; the one and only bitmap button call
      ; ------------------------------------
        invoke BmpButton,hWin,0,0,203,204,500

    .elseif uMsg == WM_SIZE

    .elseif uMsg == WM_PAINT
        invoke BeginPaint,hWin,ADDR Ps
          mov hDC, eax
          invoke Paint_Proc,hWin,hDC
        invoke EndPaint,hWin,ADDR Ps
        return 0

    .elseif uMsg == WM_CLOSE

    .elseif uMsg == WM_DESTROY
        invoke PostQuitMessage,NULL
        return 0
    .endif

    invoke DefWindowProc,hWin,uMsg,wParam,lParam

    ret

WndProc endp

; ########################################################################

TopXY proc wDim:DWORD, sDim:DWORD

    shr sDim, 1      ; divide screen dimension by 2
    shr wDim, 1      ; divide window dimension by 2
    mov eax, wDim    ; copy window dimension into eax
    sub sDim, eax    ; sub half win dimension from half screen dimension

    return sDim

TopXY endp

; #########################################################################

Paint_Proc proc hWin:DWORD, hDC:DWORD

    LOCAL btn_hi   :DWORD
    LOCAL btn_lo   :DWORD
    LOCAL Rct      :RECT

    invoke GetSysColor,COLOR_BTNHIGHLIGHT
    mov btn_hi, eax

    invoke GetSysColor,COLOR_BTNSHADOW
    mov btn_lo, eax

    return 0

Paint_Proc endp

; ########################################################################
; ###############################################################

PlayMp3File proc hWin:DWORD,NameOfFile:DWORD

      LOCAL mciOpenParms:MCI_OPEN_PARMS,mciPlayParms:MCI_PLAY_PARMS

            mov eax,hWin       
            mov mciPlayParms.dwCallback,eax
            mov eax,OFFSET Mp3Device
            mov mciOpenParms.lpstrDeviceType,eax
            mov eax,NameOfFile
            mov mciOpenParms.lpstrElementName,eax
            invoke mciSendCommand,0,MCI_OPEN,MCI_OPEN_TYPE or MCI_OPEN_ELEMENT,ADDR mciOpenParms
            mov eax,mciOpenParms.wDeviceID
            mov Mp3DeviceID,eax
            invoke mciSendCommand,Mp3DeviceID,MCI_PLAY,MCI_NOTIFY,ADDR mciPlayParms
            ret 

PlayMp3File endp

; ###############################################################

end start

jj2007


Mikl__

Hi, jj2007, LiaoMi,
thank you very much!!!

Caché GB

Hi LiaoMi

Thanks for the code you posted above. It's cool.

Quick question. In the _mp3ringtone.zip file there are two .bmp files that are used for the button.
These two images seem to be identical. Are they supposed to be like that?

Regards
Caché GB's 1 and 0-nly language:MASM

Mikl__

Hi, Caché GB!
masm32 --> examples --> Bill_Cravener --> PlayMP3
masm32 --> examples --> exampl01 --> bmbutton
The drawings are slightly different. There is a unpressed button in one image. There is the pressed button in another image.

Caché GB

#8
Hi Mikl__

Thanks a lot.

Regards
Caché GB's 1 and 0-nly language:MASM

Caché GB

Hi

A quick 64 bit interpretation of the two functions from BmpButton.asm, BmpButton proc
and its window procedure BmpButnProc proc.

Remember to replace the _UTF_16 macro with what ever string generation macro you use.



TITLE BmpButton in x64.


.code

;#############################################################################################################

BmpButton proc public hParent:qword, topX:dword, topY:dword, rnum1:dword, rnum2:DWORD, ID:DWORD

  ; parameters are,
  ; 1.  Parent handle
  ; 2/3 top X & Y co-ordinates
  ; 4/5 resource ID numbers or identifiers for UP & DOWN bitmaps
  ; 6   ID number for control

     local  hButn1:qword
     local  hImage :qword
     local  hModule:qword
     local  wid:dword
     local  hgt:dword
     local  hBmpU:qword
     local  hBmpD:qword
     local  Rct:RECT
     local  wc:WNDCLASSEX

            mov  hParent, rcx
            mov  topX, edx
            mov  topY, r8d
            mov  rnum1, r9d

            add  rsp,-068h
            and  rsp,-10h

         invoke  GetModuleHandle, null
            mov  hModule, rax

         invoke  LoadBitmap, hModule, rnum1
            mov  hBmpU, rax
         invoke  LoadBitmap, hModule, rnum2
            mov  hBmpD, rax

        _UTF_16  Bmp_Button_Class, "Bmp_Button_Class"

            mov  wc.cbSize, sizeof(WNDCLASSEX)
            mov  wc.style, CS_BYTEALIGNWINDOW
            lea  rax, BmpButnProc
            mov  wc.lpfnWndProc, rax
            mov  wc.cbClsExtra, null
            mov  wc.cbWndExtra, 16
            mov  rax, hModule
            mov  wc.hInstance, rax
            mov  wc.hbrBackground, COLOR_BTNFACE+1
            mov  wc.lpszMenuName, null
            lea  rax, Bmp_Button_Class
            mov  wc.lpszClassName, rax
            mov  wc.hIcon, null
         invoke  LoadCursor, null, IDC_ARROW
            mov  wc.hCursor, rax
            mov  wc.hIconSm, null

         invoke  RegisterClassEx, &wc

            mov  qword ptr[rsp+58h], null
            mov  rdx, hModule
            mov  qword ptr[rsp+50h], rdx
            mov  edx, ID
            mov  qword ptr[rsp+48h], rdx
            mov  rdx, hParent
            mov  qword ptr[rsp+40h], rdx
            mov  qword ptr[rsp+38h], 100
            mov  qword ptr[rsp+30h], 100
            mov  edx, topY
            mov  qword ptr[rsp+28h], rdx
            mov  edx, topX
            mov  qword ptr[rsp+20h], rdx
            mov   r9, WS_CHILD or WS_VISIBLE
            mov   r8, null
            lea  rdx, Bmp_Button_Class
            mov  rcx, WS_EX_TRANSPARENT
         invoke  CreateWindowEx

            mov  hButn1, rax

         invoke  SetWindowLong, hButn1, 0, hBmpU
         invoke  SetWindowLong, hButn1, 4, hBmpD

        _UTF_16  ButnImageClass, "STATIC"

            mov  qword ptr[rsp+58h], null
            mov  rdx, hModule
            mov  qword ptr[rsp+50h], rdx
            mov  edx, ID
            mov  qword ptr[rsp+48h], rdx
            mov  rdx, hButn1
            mov  qword ptr[rsp+40h], rdx
            mov  qword ptr[rsp+38h], 0
            mov  qword ptr[rsp+30h], 0
            mov  qword ptr[rsp+28h], 0
            mov  qword ptr[rsp+20h], 0
            mov   r9, WS_CHILD or WS_VISIBLE or SS_BITMAP
            mov   r8, null
            lea  rdx, ButnImageClass
            mov  rcx, 0
         invoke  CreateWindowEx

           mov  hImage, rax

         invoke  SendMessage, hImage, STM_SETIMAGE, IMAGE_BITMAP, hBmpU

         invoke  GetWindowRect, hImage, &Rct
         invoke  SetWindowLong, hButn1, 8, hImage

            mov  eax, Rct.bottom
            mov  edx, Rct.top
            sub  eax, edx
            mov  hgt, eax

            mov  eax, Rct.right
            mov  edx, Rct.left
            sub  eax, edx
            mov  wid, eax

         invoke  SetWindowPos, hButn1, HWND_TOP, 0, 0, wid, hgt, SWP_NOMOVE

         invoke  ShowWindow, hButn1, SW_SHOW

            mov  rax, hButn1

            ret

BmpButton endp

;#############################################################################################################

BmpButnProc proc hWin:qword, uMsg:qword, wParam:qword, lParam:qword

     local  hBmpU :qword
     local  hBmpD :qword
     local  hImage:qword
     local  hParent:qword

     local  ID:sdword
     local  ptX:dword
     local  ptY:dword
     local  bWid:dword
     local  bHgt:dword
     local  Rct:RECT

            mov  hWin, rcx
            mov  uMsg, rdx
            mov  wParam, r8
            mov  lParam, r9

            add  rsp,-38h
            and  rsp,-10h

          .data
                 cFlag  dd  0      ; a GLOBAL variable for the "clicked" setting
          .code

            cmp  uMsg, WM_LBUTTONDOWN
            jne  @B0020

         invoke  GetWindowLong, hWin, 4
            mov  hBmpD, rax
         invoke  GetWindowLong, hWin, 8
            mov  hImage, rax
         invoke  SendMessage, hImage, STM_SETIMAGE, IMAGE_BITMAP, hBmpD
         invoke  SetCapture, hWin

            mov  cFlag, true
            jmp  @C0010

        @B0020:

            cmp  uMsg, WM_LBUTTONUP
            jne  @C0010

            cmp  cFlag, false
            jne  @B0022
            ret

        @B0022:

            mov  cFlag, false

         invoke  GetWindowLong, hWin, 0
            mov  hBmpU, rax
         invoke  GetWindowLong, hWin, 8
            mov  hImage, rax
         invoke  SendMessage, hImage, STM_SETIMAGE, IMAGE_BITMAP, hBmpU

            mov  rax, lParam
           cwde
            mov  ptX, eax
            mov  rax, lParam
            rol  eax, 16
           cwde
            mov  ptY, eax

         invoke  GetWindowRect, hWin, &Rct

            mov  eax, Rct.right
            mov  edx, Rct.left
            sub  eax, edx
            mov  bWid, eax

            mov  eax, Rct.bottom
            mov  edx, Rct.top
            sub  eax, edx
            mov  bHgt, eax

      ; --------------------------------
      ; exclude button releases outside of the button
      ; rectangle from sending message back to parent
      ; --------------------------------
            cmp  ptX, 0
            jle  @B0040
            cmp  ptY, 0
            jle  @B0040
            mov  eax, bWid
            cmp  ptX, eax
            jge  @B0040
            mov  eax, bHgt
            cmp  ptY, eax
            jge  @B0040

         invoke  GetParent, hWin
            mov  hParent, rax
         invoke  GetDlgCtrlID, hWin
            mov  ID, eax
         invoke  SendMessage, hParent, WM_COMMAND, ID, hWin

        @B0040:

         invoke  ReleaseCapture

        @C0010:

         invoke  DefWindowProc, hWin, uMsg, wParam, lParam

            ret

BmpButnProc endp

;#############################################################################################################
Caché GB's 1 and 0-nly language:MASM

Mikl__

#10
Hi All!
I play in synchronous mode a wav-file from a buffer in memory. The low-level functions waveOutPrepareHeader, waveOutUnprepareHeader, waveOutOpen, waveOutClose, waveOutWrite are used. There are wav-/source-/exe-files in attached; GUI #
include win64a.inc
WAVEHDR struct
lpData QWORD ?
dwBufferLength DWORD ?
dwBytesRecorded DWORD ?
dwUser QWORD ?
dwFlags DWORD ?
dwLoops DWORD ?
lpNext QWORD ?
reserved qword ?
WAVEHDR ends

WHDR_DONE equ 1

.code
WinMain proc
local hGout:qword
local p:qword
local FSize:dword
local hFile:dword
local szReadWrite:qword
local hWaveOut:qword
local lpwiocb:WAVEHDR

mov ecx,offset wav_file
invoke CreateFile,,GENERIC_READ,0,0,OPEN_EXISTING,\
        FILE_ATTRIBUTE_ARCHIVE,0
        mov hFile,eax
        invoke GetFileSize,eax,0
mov FSize,eax
invoke GlobalAlloc,GHND or GMEM_DDESHARE,eax
mov hGout,rax
invoke GlobalLock,eax
mov p,rax
lea r9d,szReadWrite
        invoke ReadFile,hFile,eax,FSize,,0
        invoke CloseHandle,hFile
invoke GlobalUnlock,hGout
lea ecx,hWaveOut
        xor r9,r9
mov [rsp+20h],r9
mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
mov r8,p
add r8d,14h
or edx,WAVE_MAPPER
invoke waveOutOpen
lea edx,lpwiocb
mov edi,edx
xor eax,eax
mov ecx,(sizeof WAVEHDR)/8
        rep stosq
mov rax,p
add rax,2Ch
mov [rdx].WAVEHDR.lpData,rax
mov eax,FSize
sub eax,2Ch
mov [rdx].WAVEHDR.dwBufferLength,eax
invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR

lea edx,lpwiocb
invoke waveOutWrite,hWaveOut,,sizeof WAVEHDR
@@: test lpwiocb.dwFlags,WHDR_DONE
jz @b
lea edx,lpwiocb
invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
invoke waveOutClose,hWaveOut
invoke RtlExitUserProcess,NULL
WinMain endp
wav_file db '03.wav',0
end

jj2007

Hi Mikl,

Looks good, and looks simple :thumbsup:

What about mp3 then? There is some code here, but the guy never got an answer :cool:

NoCforMe

JJ, that link doesn't work. Did windowsquestions.com go off the air?
Assembly language programming should be fun. That's why I do it.