• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

Recent posts

#21
Brians Board / Re: Any Good news regarding PB...
Last post by Chris Chancellor - January 11, 2020, 12:35:13 AM
Hello there 2020  and nothing from PB on 64bit

QuoteThe Drakes are a big disappointment imo.

;D   this is an absolute truth  and that O2 is our only light at the tunnel end

#22
C++ programming (SDK style) / HAL 9000
Last post by Patrice Terrier - January 02, 2020, 10:03:37 PM
Here is another video showhing ObjReader64 version 2.85 playing a static animation.
video

The audio track was extracted from "2001 A Space Odyssey" movie.

#23
C++ programming (SDK style) / Spitfire MkVb animated
Last post by Patrice Terrier - December 30, 2019, 11:40:20 AM
Here is a video showhing ObjReader64 version 2.85 playing a real time animation.
Video

The audio track is the real sound of a Rolls Royce Merlin engine...

Note: The video is not as good as playing it directly with ObjReader64  ;)



#24
General Discussion / Re: mp3 duration
Last post by Juergen Kuehlwein - December 27, 2019, 08:59:04 PM
> I have one: AfxGuid (in AfxCOM.inc)

Great, thanks!
#25
General Discussion / Re: mp3 duration
Last post by José Roca - December 27, 2019, 01:23:12 PM
> would be nice to have something like GUID$ for FB too !

I have one: AfxGuid (in AfxCOM.inc)


' ========================================================================================
' Converts a string into a 16-byte (128-bit) Globally Unique Identifier (GUID)
' To be valid, the string must contain exactly 32 hexadecimal digits, delimited by hyphens
' and enclosed by curly braces. For example: {B09DE715-87C1-11D1-8BE3-0000F8754DA1}
' If pwszGuidText is omited, AfxGuid generates a new unique guid.
' Remarks: I have need to call the UuidCreate function dynamically because, at the time of
' writing, the library for the RPCRT4.DLL seems broken and the linker fails.
' ========================================================================================
PRIVATE FUNCTION AfxGuid (BYVAL pwszGuidText AS WSTRING PTR = NULL) AS GUID
   DIM rguid AS GUID
   IF pwszGuidText = NULL THEN
      ' // Generate a new guid
      DIM AS ANY PTR pLib = DyLibLoad("RPCRT4.DLL")
      IF pLib  THEN
         DIM pProc AS FUNCTION (BYVAL Uuid AS UUID PTR) AS RPC_STATUS
         pProc = DyLibSymbol(pLib, "UuidCreate")
         IF pProc THEN pProc(@rguid)
         DyLibFree(pLib)
      END IF
   ELSE
      CLSIDFromString(pwszGuidText, @rGuid)
   END IF
   RETURN rguid
END FUNCTION
' ========================================================================================

#26
General Discussion / Re: mp3 duration
Last post by Juergen Kuehlwein - December 27, 2019, 12:44:09 PM
PB code:

#COMPILE EXE 
#DIM ALL

'#utility roca3                                        'use José Roca includes

#Include "win32api.inc"
#Include "shobjidl.inc"
#Include "propkey.inc"


FUNCTION duration(file AS WSTRINGZ) AS LONG
'***********************************************************************************************
' return duration of an audio file in ms, -1 for fail
'***********************************************************************************************
LOCAL d          AS QUAD
LOCAL propVar    AS PropVariant
LOCAL hr         AS LONG
LOCAL pPropStore AS IPropertyStore


  hr = SHGetPropertyStoreFromParsingName(BYVAL VARPTR(file), NOTHING, %GPS_DEFAULT, $IID_IPropertyStore, pPropStore)
  IF hr = %S_OK THEN
    hr = pPropStore.GetValue(PKEY_Media_Duration, propVar)
    IF hr = %S_OK THEN
      d = propVar.uhVal                               'time in 100ns

    ELSE
      FUNCTION = -1
      EXIT FUNCTION
    END IF
   
    pPropStore = NOTHING

  ELSE
    FUNCTION = -1
    EXIT FUNCTION
  END IF


  FUNCTION = d/10000                                  'time in ms


END FUNCTION


FUNCTION PBMAIN () AS LONG
'***********************************************************************************************
' -> change paths ...  (must be a full path)
'***********************************************************************************************

  ? STR$(duration("C:\PBwin10\IDE\Projects\mp3\blues.mp3"))
  ? STR$(duration("C:\PBwin10\IDE\Projects\mp3\cher.mid"))
  ? STR$(duration("C:\PBwin10\IDE\Projects\mp3\ring05.wav"))
 

END FUNCTION 


FB code:

'#COMPILER FREEBASIC
'#COMPILE CONSOLE 32 '64


#INCLUDE ONCE "windows.bi"
#INCLUDE ONCE "win\shobjidl.bi"


FUNCTION duration (file AS WSTRING) AS LONG
'***********************************************************************************************
' return duration of an audio file in ms, -1 for fail
'***********************************************************************************************
DIM d                   AS ULONGINT
DIM propVar             AS PropVariant
DIM hr                  AS HRESULT
DIM pPropStore          AS IPropertyStore PTR
DIM PKEY_Media_Duration AS PROPERTYKEY

'***********************************************************************************************
' MACRO PKEY_Media_Duration = GUID$("{64440490-4C8B-11D1-8B70-080036B11A03}") & MKDWD$(3)
' would be nice to have something like GUID$ for FB too !
'***********************************************************************************************
  PKEY_Media_Duration.fmtid.data1    = &H64440490
  PKEY_Media_Duration.fmtid.data2    = &H4C8B
  PKEY_Media_Duration.fmtid.data3    = &H11D1
  PKEY_Media_Duration.fmtid.data4(0) = &H8B
  PKEY_Media_Duration.fmtid.data4(1) = &H70
  PKEY_Media_Duration.fmtid.data4(2) = &H08
  PKEY_Media_Duration.fmtid.data4(3) = &H00
  PKEY_Media_Duration.fmtid.data4(4) = &H36
  PKEY_Media_Duration.fmtid.data4(5) = &HB1
  PKEY_Media_Duration.fmtid.data4(6) = &H1A
  PKEY_Media_Duration.fmtid.data4(7) = &H03
  PKEY_Media_Duration.pid   = 3


  coinitialize(0)                                     'a must in FB

  hr = SHGetPropertyStoreFromParsingName(varptr(file), 0, GPS_DEFAULT, @IID_IPropertyStore, @pPropStore)
  IF hr = S_OK THEN
    hr = IPropertyStore_GetValue(pPropStore, @PKEY_Media_Duration, @propVar)
    IF hr = S_OK THEN
      d = propVar.uhVal.QuadPart                      'time in 100ns

    ELSE
      couninitialize
      RETURN -1
    END IF
   
    IPropertyStore_Release(pPropStore)

  ELSE
    couninitialize
    RETURN -1
  END IF


  couninitialize
  RETURN d/10000                                      'time in ms


END FUNCTION


'***********************************************************************************************
' -> change paths ...  (must be a full path)
'***********************************************************************************************

  PRINT duration("C:\PBwin10\IDE\Projects\mp3\blues.mp3")
  PRINT duration("C:\PBwin10\IDE\Projects\mp3\cher.mid")
  PRINT duration("C:\PBwin10\IDE\Projects\mp3\ring05.wav")


  SLEEP
#27
General Discussion / Re: mp3 duration
Last post by Juergen Kuehlwein - December 27, 2019, 11:38:49 AM
Yes, for compression formats with a variable bit rate like mp3 you cannot just divide the number of frames by the rate (fps). But you can calculate the exact duration by looping through the frames (i think this is what BASS_STREAM_PRESCAN does). There is sample code for this at various places in the net.

In the meantime i found what i was looking for. What an effort for a few lines of code! In fact retrieving the duration form the propertystore delivers correct results (even for mp3, Windows 7 and 10). I will post code here soon.
#28
General Discussion / Re: mp3 duration
Last post by Patrice Terrier - December 27, 2019, 10:32:14 AM
I think to remember from the top of my head that mp3 duration is only an approximation, because of the audio signal compression.
(mostly with mp3 using a variable bit rate)
The true length can be known only when audio comes to full completion.

This is the reason why Bass.dll use the BASS_STREAM_PRESCAN flag to return an accurate length.

What you could do is to encode the correct duration into the ID3 tag (there are many utilities able to do this).
Or convert the mp3 to ogg with Audacity if you don't need the ID3 tag.
#29
General Discussion / Re: mp3 duration
Last post by Juergen Kuehlwein - December 26, 2019, 10:04:23 PM
Thanks José,


good to know that there is a FreeBASIC equivalent. I already know how to do it (PB and FB). But the problem remains the same, IMediaSeeking GetDuration returns a wrong result for mp3 files. Seems i need a translation of Bob Carvers´s code for that.
#30
General Discussion / Re: mp3 duration
Last post by José Roca - December 26, 2019, 07:34:03 PM
You can look at my CAfxMp3.inc file, that includes de CAfxMp3 class. It gets the duration callig the GetDuration method of the IMediaSeeking interface. Be aware that this method returns 10,000,000 for a second (100-nanosecond units).

BTW I ported this class to FreeBasic (CDSAudio class in CDSAudio.inc).
Documentation: https://github.com/JoseRoca/WinFBX/blob/master/docs/COM/CDSAudio%20Class.md