I'd like a reallllly simple WAV player. Just something I can fire up, select the file to play and have it play in the background while I do other stuff.
I tried PlaySound():
INVOKE PlaySoundA, ADDR SoundFilename, NULL, SND_FILENAME ;OR SND_ASYNC
It works--it plays the sound--but it has problems, and I don't think it's the right thing to use here.
No problem for short sound files, but when I tried to play a song of a few minutes length (~23 MB), it played to a certain point, then stopped. Plus I couldn't get the "async" flag to work (no sound at all if I use this flag). The one page I found in MSDN (http://msdn.microsoft.com/en-us/library/aa909766.aspx) about this function says:
QuoteThe sound specified by pszSound must fit into available physical memory and be playable by an installed waveform-audio device driver.
So it apparently does little or no buffering of the WAV data. (I used PlaySoundA() because this was all I could find in the MASM32 include and lib files; no PlaySound().)
The documentation on MSDN is very confusing. All the descriptions I found seem to apply to weird things like Windows CE and Windows Mobile, or else they give C++ or C# examples that need a certain SDK or language-specific features. (Then there's the whole "core audio" API, which requires Vista or later.)
I
think I want to use some of the
wavexxxx() functions instead. All I want is a really simple player; all it needs is to be able to select a WAV file, and maybe a "stop" button to kill it. Don't really even need positioning controls, pause, etc., though these would probably be easy enough to add.
Can someone point me to a simple tutorial on this, or maybe a working example somewhere, that shows how to use these functions?
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757160%28v=vs.85%29.aspx
that is just one of the functions
look to the left-hand side for others
there is a bit of reading to do :P
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757151%28v=VS.85%29.aspx
Dave has you on the correct path and with my simple mp3 player example you should have no trouble making your own wave file player. Simply change the DlgDirList functions lpPathSpec in my example to "*.wav" and it will play wave files.
http://www.quickersoft.com/examples/PlayMp3.zip
Try if it stops early with your 23 MB file.
include \masm32\include\masm32rt.inc
include \masm32\include\winmm.inc
includelib \masm32\lib\winmm.lib
.data
playthis db "play "
buffer db 128 dup(?)
.code
start:
mov esi, offset buffer
; drag a valid wav file over the executable,
; e.g. C:\WINDOWS\Media\Windows XP Startup.wav
invoke GetCL, 1, esi
.if rv(GetShortPathName, esi, esi, 127)
sub esi, 5
invoke mciSendString, esi, 0, 0, 0
.endif
inkey "bye"
exit
end start
Hmm; I tried that, jj, but it doesn't work at all. Here's the bulk of my program:
.data
SoundCommand DB "play \SAVE\Sounds\Music\Balkan-E. European\Bulgarian\Gumzoviana.wav", 0
ErrorMsgBuffer DB 200 DUP (?)
;============================================
; CODE LIVES HERE
;============================================
.code
start: INVOKE mciSendString, OFFSET SoundCommand, NULL, 0, 0
OR EAX, EAX
JZ @F
INVOKE mciGetErrorString, EAX, OFFSET ErrorMsgBuffer, SIZEOF ErrorMsgBuffer
INVOKE MessageBox, 0, OFFSET ErrorMsgBuffer, NULL, MB_OK
@@: INVOKE ExitProcess, EAX
All I get is an error message that says "The specified device is not open or is not recognized by MCI".
Bill, I'm going to look at your example next.
Bill, I just edited and built your little app. It works, but I've got some questions.
I just changed ".mp3" to ".wav" as you suggested, and it does play WAV files (all the way through, too). But even though I can select and play MP3 files as well, they don't play ... correctly. Sound all chopped up.
I notice some minor buffering glitches too, which must be due to the way the file is being handled by the mcixxx() functions.
I notice you open a device called "MPEGVideo"; shouldn't this be changed if I want to play WAVs? or not? (seems to work OK).
By the way, I hate your user interface (and I mean this in the nicest possible way). Very hard to drill back up through a disk directory structure.
Thanks for the app, and thanks in advance for any further answers.
Update: Just remade the app changing the ".wav" back to ".mp3". Did you know it makes no difference? You can play WAV or MP3 files in either case.
I tried playing some MP3s. The files I have don't play well at all (all chopped up, as noted above), but your sample MP3 plays just fine. For some reason it doesn't seem to like my MP3s. (Mine were made with a Sound Forge plug-in and play on every other player I've used.) No big deal, just thought you'd like to know.
Quote from: NoCforMe on January 10, 2012, 06:13:36 AM
Hmm; I tried that, jj, but it doesn't work at all.
Your filename has spaces. Won't work with spaces.
Hi NoCforMe,
Many MP3 files are VBR encoded, these wll have problems with mciXXX functions as far as I remember (its been quite a while since I've used them). You can check for a XING signature in the MP3 file to see if it is VBR, I posted a program (http://www.masm32.com/board/index.php?topic=10610.0) to extract the information from MP3 files that demonstrates how to do this. It will also allow you to display other information about the MP3 at the same time.
Edgar
Quote from: jj2007 on January 10, 2012, 06:37:34 AM
Quote from: NoCforMe on January 10, 2012, 06:13:36 AM
Hmm; I tried that, jj, but it doesn't work at all.
Your filename has spaces. Won't work with spaces.
And yet PlaySound() can play that same file, coded the same way.
I thought the problem might be that you never opened the sound device, like Bill does in his little app (using mciSendCommand(MCI_OPEN) ).
NoC,
There could be a problem with your audio setup or Windows version. I forgot that my example should work with spaces, too, since it uses GetShortPathName. On my puter, WinXP SP2, it works just fine, you can drag *.wav or *.mp3 over the exe and it starts playing until you hit the key.
See also Edgar's comment concerning mp3 files (but your problem is wav...).
You know if you're going to be serious about playing MP3's the mci is very limited. You should think about DirectShow. Unfortunately (for some) it is only available as a COM interface but it is extremely easy to use. I have cut the appropriate parts out of a project I was working on (but have shelved indefinitely) and pasted them here. It is in GoAsm syntax and requires my headers but I am sure someone here can translate them for you. It plays MP3s very well and if you want to get deeper you can control pretty much everything about your player.
Note that this should play WAVs as well but I have never tried it.
Sorry about the length of this code, I didn't want to build a project.
STRINGS UNICODE
#DEFINE UNICODE
#define WIN32_LEAN_AND_MEAN
#DEFINE WINVER NTDDI_WINXP
#DEFINE FILTERAPI
#DEFINE LINKFILES
#DEFINE LINKVCRT
#DEFINE CCUSEORDINALS
#include "WINDOWS.H"
#include "macros.h"
#include "mmsystem.h"
#include "strmif.h"
#include "control.h"
#include "uuids.h"
#IF X64
S=8
#ELSE
S=4
#ENDIF
DATA SECTION
pigb PTR NULL
pimc PTR NULL
pimex PTR NULL
piba PTR NULL
pims PTR NULL
ready BOOL FALSE
duration LONGLONG 0
IID_IGraphBuilder GUID GUID_IID_IGraphBuilder
IID_IMediaControl GUID GUID_IID_IMediaControl
IID_IMediaEventEx GUID GUID_IID_IMediaEventEx
IID_IBasicAudio GUID GUID_IID_IBasicAudio
IID_IMediaSeeking GUID GUID_IID_IMediaSeeking
CLSID_FilterGraph GUID GUID_CLSID_FilterGraph
TIME_FORMAT_MEDIA_TIME GUID GUID_TIME_FORMAT_MEDIA_TIME
MP3File DUS "Some.mp3",0
evcode DD 0
CODE SECTION
// Be sure to initialize COM
invoke CoInitialize,NULL
// To play a file just do this
invoke Load,offset MP3File
// Volume is 0 (full) to -10000 (mute)
invoke SetVolume,0
invoke Play
// Wait for it to complete
invoke WaitForCompletion,10000000,offset evcode
// Cleanup the interfaces
call Cleanup
// When your program is done shut down COM
invoke CoUninitialize
// The functions (I have a few more but they require a lot of setup code)
Cleanup:
cmp S[pimc],0
je >
CoInvoke(pimc,IMediaControl.Stop)
:
cmp S[pigb],0
je >
CoInvoke(pigb,IGraphBuilder.Release)
mov S[pigb],NULL
:
cmp S[pimc],0
je >
CoInvoke(pimc,IMediaControl.Release)
mov S[pimc],NULL
:
cmp S[pimex],0
je >
CoInvoke(pimex,IMediaEventEx.Release)
mov S[pimex],NULL
:
cmp S[piba],0
je >
CoInvoke(piba,IBasicAudio.Release)
mov S[piba],NULL
:
cmp S[pims],0
je >
CoInvoke(pims,IMediaSeeking.Release)
mov S[pims],NULL
:
mov D[ready],FALSE
RET
Load FRAME szFile
LOCAL LocResult:D
call Cleanup
mov D[ready],FALSE
invoke CoCreateInstance,offset CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,offset IID_IGraphBuilder,offset pigb
test eax,eax
jnz >>.EXIT
xor eax,eax
mov [LocResult],eax
CoInvoke(pigb,IGraphBuilder.IUnknown.QueryInterface,offset IID_IMediaControl,offset pimc)
or [LocResult],eax
CoInvoke(pigb,IGraphBuilder.IUnknown.QueryInterface,offset IID_IMediaEventEx,offset pimex)
or [LocResult],eax
CoInvoke(pigb,IGraphBuilder.IUnknown.QueryInterface,offset IID_IBasicAudio,offset piba)
or [LocResult],eax
CoInvoke(pigb,IGraphBuilder.IUnknown.QueryInterface,offset IID_IMediaSeeking,offset pims)
or [LocResult],eax
cmp D[LocResult],0
jne >.EXIT
CoInvoke(pigb,IGraphBuilder.RenderFile,[szFile],NULL)
test eax,eax
jnz >.EXIT
mov D[ready],TRUE
cmp S[pims],0
je >>.EXIT
CoInvoke(pims,IMediaSeeking.SetTimeFormat,offset TIME_FORMAT_MEDIA_TIME)
CoInvoke(pims,IMediaSeeking.GetDuration,offset duration)
.EXIT
mov eax,[ready]
ret
ENDF
Play:
cmp D[ready],FALSE
je >>.EXIT
cmp S[pimc],0
je >>.EXIT
CoInvoke(pimc,IMediaControl.Run)
ret
.EXIT
mov eax,-1
ret
Pause:
cmp D[ready],FALSE
je >>.EXIT
cmp S[pimc],0
je >>.EXIT
CoInvoke(pimc,IMediaControl.Pause)
ret
.EXIT
mov eax,-1
ret
Stop:
cmp D[ready],FALSE
je >>.EXIT
cmp S[pimc],0
je >>.EXIT
CoInvoke(pimc,IMediaControl.Stop)
ret
.EXIT
mov eax,-1
ret
WaitForCompletion FRAME msTimeout, pEvCode
cmp D[ready],FALSE
je >>.EXIT
cmp S[pimex],0
je >>.EXIT
CoInvoke(pimex,IMediaEventEx.WaitForCompletion,[msTimeout],[pEvCode])
cmp eax,0
jne >.EXIT
mov eax,1
ret
.EXIT
mov eax,0
ret
ENDF
SetVolume FRAME vol
cmp D[ready],FALSE
je >>.EXIT
cmp S[piba],0
je >>.EXIT
CoInvoke(piba,IBasicAudio.put_Volume,[vol])
ret
.EXIT
mov eax,-1
ret
ENDF
GetVolume FRAME pvol
cmp D[ready],FALSE
je >>.EXIT
cmp S[piba],0
je >>.EXIT
CoInvoke(piba,IBasicAudio.get_Volume,[pvol])
ret
.EXIT
mov eax,-1
ret
ENDF
GetCurrentPosition FRAME pInt64curpos
cmp D[ready],FALSE
je >>.EXIT
cmp S[pims],0
je >>.EXIT
mov eax,[pInt64curpos]
mov D[eax],-1
mov D[eax+4],-1
CoInvoke(pims,IMediaSeeking.GetCurrentPosition,[pInt64curpos])
ret
.EXIT
mov eax,-1
ret
ENDF
SetPositions FRAME pINT64Current, pINT64Stop, bAbsolutePositioning
LOCAL Posflags:D
mov D[Posflags],0
cmp D[ready],FALSE
je >>.EXIT
cmp S[pims],0
je >>.EXIT
cmp D[bAbsolutePositioning],0
je >
mov D[Posflags], AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame
jmp >>.SETPOS
:
mov D[Posflags], AM_SEEKING_RelativePositioning | AM_SEEKING_SeekToKeyFrame
.SETPOS
CoInvoke(pims,IMediaSeeking.SetPositions,[pINT64Current], [Posflags], [pINT64Stop], [Posflags])
ret
.EXIT
mov eax,-1
ret
ENDF
Quote from: NoCforMe on January 10, 2012, 06:32:44 AM
I notice you open a device called "MPEGVideo"; shouldn't this be changed if I want to play WAVs? or not? (seems to work OK).
Using the MPEGVideo type you can play almost all of the newest media files such as divx, xvid, mp3, avi, wav, mpeg, mpg, wma and wmv. If I recall correctly earlier versions of Windows win.ini file had a list of supported media file types that the MPEGVideo type supported. The MPEGVideo type refers to Windows system default media driver which as we know can play most anything including MP3 using I think DirectShow which is the technology that replaced MCI some 10 years or more ago. If you have a third-party driver with a higher precedence that claims to support MP3 but in fact doesn't or a third-party installer that has broke MPEGVideo's registration you may get stuttering in your playback. It is not the fault of my simple media player example.
Quote from: NoCforMe on January 10, 2012, 06:32:44 AM
By the way, I hate your user interface (and I mean this in the nicest possible way). Very hard to drill back up through a disk directory structure.
Come on NoCforMe just what did you expect for free its intention is to be simple. What you do with it from there is up to you. Now if you want to open up your wallet I'll do you up something real fancy. :bg
QuoteBill Cravener http://www.quickersoft.com/examples/PlayMp3.zip
Now it is clear how players make (http://smiles.kolobok.us/light_skin/tender.gif)
Thank you bomz! :bg
First time I've ever tested my simple media player example on a full length mp3 and it appears to work perfectly. :bg
Crank it up!! HillbillyHerald.mp3 (http://www.quickersoft.com/examples/HillbillyHerald.mp3)
Bill CravenerQuote.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
FileName db "Sample.avi",0
szMCIdll db "msvfw32.dll", 0
szMCIWndCreate db "MCIWndCreate", 0
.code
start:
invoke LoadLibrary, addr szMCIdll
push eax
invoke GetProcAddress, eax, addr szMCIWndCreate
push offset FileName
push 0
push 0
push 0
call eax
call FreeLibrary
invoke MessageBox,0,0,0,0
invoke ExitProcess,0
end start
(http://s47.radikal.ru/i115/0810/9a/919ffed6ae3a.gif)
:wink clearer in GoAsm
#DEFINE WINVER NTDDI_WINXP // Target system is XP
#DEFINE FILTERAPI // Generate errors for unavailable/deprecated API
#define LINKFILES // Link the DLL libraries
#INCLUDE Windows.h // Core headers
DATA SECTION
FileName db "Sample.avi",0
CODE SECTION
Start:
invoke MCIWndCreate,0,0,0,offset FileName
invoke MessageBox,0,0,0,0
invoke ExitProcess,0
yah - we need to create a vfw32.inc and vfw32.lib that get functions from avicap32.dll, avifil32.dll, and msvfw32.dll
not from vfw32.dll, which does not exist
vfw32 is, however, the correct name for the include and import library
at least, that is how MS C handles it
i suppose we could put the functions in 3 seperate INC/LIB pairs
vfw32.inc/lib in masm32 version 10 do not have the MCIWndCreate(A/W) functions
vfw32.inc/lib in masm32 version 11 do have the MCIWndCreate(A/W) functions, but try to import from the nonexistant DLL
i suppose this should be a bug report in the MASM32 project subforum :P
I'm sure I posted an import library and an incomplete include file (for everything but the procedure prototypes, which are in separate include file that AFAIK is complete) somewhere here, but I can't seem to find it now, so here they are again.
How make player? I try hook mciSendCommand
ok - my next question is...
how do we emulate all these macros ? :P
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743598%28v=VS.85%29.aspx
i guess someone with a C compiler can do it
maybe this guy has already done so
it looks like many of the macros are covered in ASM source...
http://4coder.org/assembler-source-code/73/
you can download the entire package, or modify the URL as follows for an example...
http://4coder.org/assembler-source-code/73/libmci/MCIWndCanConfig.asm.html
ok - well, it's not perfect
that particular function is supposed to be a macro, not a proc
but, the code is there to figure out how to write the macro
When I change my simple multimedia example so that it can list all file types it plays anything I throw at it. The example link below includes the player and a small AVI, WMV, WAV, MP3 and MPG-1 sample media file. At least on my Windows 7 64 bit machine and my old XP Home Edition SP3 machine it plays them all perfectly. Using my example my Win 7 machine will also play MPG-2's but my XP machine will not.
http://www.quickersoft.com/examples/Multimedia.zip
i am running XP MCE2005 SP3
it plays the movie clip fine, Bill :U
all you need is an MPEG-2 codec
here is one i know works...
http://www.free-codecs.com/download/stinky_mpeg_2_codec.htm
i use the k-lite mega codec package, which has all kinds of stuff :P
Hi Dave, yes I figured that was the case. I need to spend some time on my XP box and get everything up to date. It really gets ignored now that I have this new Win 7 box. :bg
well - MCE won't work without an MPEG-2 codec
oddly enough, MS does not provide one - lol
for that reason, MCE was only available in OEM machines, and had to be bundled with some kind of player that provided one
this Sony machine came with WinDVD, which includes the codec
the MPEG-2 codec is also required to play DVD's
Bill Cravener
Install K-Lite Codec Pack and you Simple MP3 Player may show all video files
http://www.erightsoft.com/SUPER.html - Starnge When I install this converter all video files may show too, including MKV conteiners
Here is one that takes a file from the commandline and plays it immediately.
I had lots of trouble playing avi files (decompressor not available) until I found a site that said "rename them to mpg", and wow, it worked :dazzled:
little secret - that also works for VOB files :P
although - i didn't have any luck with that player - lol
It 's depend from codecs which install and registering in system
http://www.codecguide.com/download_k-lite_codec_pack_full.htm
Quote from: dedndave on January 15, 2012, 01:29:59 AM
little secret - that also works for VOB files :P
although - i didn't have any luck with that player - lol
You mean the one I posted? I just tried my luck with Hutch's suggestion (http://www.masm32.com/board/index.php?topic=18169.0) but no luck - even renaming to *.mpg just gave a message "damaged file". It opens fine in other players, though, meaning the codecs are there but mci is not able to find them.
For my own private *.avi files instead, renaming to *.mpg helps. If I use them as *.avi, there is a message "video not available", sound works (!), and the mouse is almost blocked.
The whole video business is very, very messy on Windows. I remember that frequently Windows doesn't know about its own formats. Greetings to Redmond :wink
i tried a variety of file types - mp4, m4v, flv, and so on - all of which i have codecs for
many of them would not play with your player
by renaming them to mpg, they did play
it did not work for vob's - although, i have had success with that when i did not have a full set of codecs
Dave I have a copy of Richard Hammond's BBC documentry of Evil Knievel in VOB format (last he ever gave) its an hour long and it plays perfectly on my Win 7 machine from that simple media player example of mine. I'm quite certain using the MPEGVideo type you can play most any media file if the correct codec is installed on a machine even VOB's.
yah - VOB files are containers for MPEG video information :P
Dave,
Well to be honest about it I'm not all that savvy about all that media shit, I get an idea for an example I want to create and I start digging into Microsoft's SDK. That's how I derive every example I've created over all these years and at the same time having one hell of a lot of fun doing so. :bg
i hear ya, Bill
i am a novice, too - lol
i do have some interest - i'd like to learn more about it
for now, i am just trying to learn my way around the API :P
(http://smiles.kolobok.us/light_skin/vava.gif)
Quote.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comctl32.inc
include \masm32\include\winmm.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comctl32.lib
includelib \masm32\lib\winmm.lib
HookProc PROTO :DWORD, :DWORD, :DWORD
HookWndProc PROTO :DWORD, :DWORD, :DWORD, :DWORD
.data
mestitle db "Bomz",0
Mp3Device db "MPEGVideo",0
FileName db "Seven.Years.in.Tibet.1997.BDRip.720p.mkv",0
.data?
mciOpenParms MCI_OPEN_PARMS <>
mciPlayParms MCI_PLAY_PARMS <>
Mp3DeviceID dd ?
hHook dd ?
ThreadId dd ?
.code
start:
invoke GetCurrentThreadId
mov ThreadId, eax
invoke SetWindowsHookEx,WH_CALLWNDPROC,addr HookProc,NULL,ThreadId
mov hHook, eax
mov eax,0
mov mciPlayParms.dwCallback,eax ; функция которой послать сообщение MM_MCINOTIFY об окончании воспроизведения
lea eax, Mp3Device
mov mciOpenParms.lpstrDeviceType,eax
lea eax,FileName
mov mciOpenParms.lpstrElementName,eax
invoke mciSendCommand,0,MCI_OPEN,MCI_OPEN_TYPE or MCI_OPEN_ELEMENT,ADDR mciOpenParms
;invoke MessageBox,0,0,ADDR mestitle,MB_ICONASTERISK
mov eax,mciOpenParms.wDeviceID
mov Mp3DeviceID,eax
invoke mciSendCommand,Mp3DeviceID,MCI_PLAY,MCI_NOTIFY,ADDR mciPlayParms
invoke MessageBox,0,0,ADDR mestitle,0;MB_ICONASTERISK
invoke mciSendCommand,Mp3DeviceID,MCI_CLOSE,0,0
invoke ExitProcess,0
HookProc PROC nCode:DWORD,wParam:DWORD,lParam:DWORD
.if nCode==HC_ACTION
mov edx, lParam
assume edx:PTR CWPSTRUCT
.if [edx].message == WM_INITDIALOG
invoke SetWindowText, [edx].hwnd, addr Mp3Device
;invoke MessageBeep, MB_ICONASTERISK
invoke UnhookWindowsHookEx,hHook
.endif
assume edx:nothing
.endif
invoke CallNextHookEx,hHook,nCode,wParam,lParam
xor eax,eax
ret
HookProc endp
end start