Je suis tombé la page de documentation sur le format wave (qu'on trouve aussi en téléchargement). A partir de ca j'ai fait le jeu de fonctions ci-dessous
Avec un petit exemple d'utilisation que vous pouvez trouver scope.zip


Bien entendu je ne compte pas m'arrêter là et j'espère bien corriger les bugs présents et ajouter tout plein d'autres fonctions ^^
Code : Tout sélectionner
;***********************************************
;* Echange le contenu de deux zones de mémoire *
;***********************************************
Procedure Swap(*a.l, *b.l, Size.l)
Protected *c.l
If *a <> #NULL And *b <> #NULL
*c = AllocateMemory(Size)
If *c <> #NULL
CopyMemory(*a, *c, Size)
CopyMemory(*b, *a, Size)
CopyMemory(*c, *b, Size)
FreeMemory(*c)
EndIf
EndIf
EndProcedure
;***********************************
;* Déclaration des structures Wave *
;***********************************
Structure WaveFileHeader
dwRiff.l
dwSize.l
dwWave.l
EndStructure
Structure WaveChunk
dwTag.l
dwSize.l
EndStructure
Structure WaveFormatChunk
dwFormat.l
dwSize.l
wFormatTag.w
wChannels.w
dwSamplesPerSec.l
dwAvgBytesPerSec.l
wBlockAlign.w
wBitsPerSample.w
EndStructure
Structure WaveDataChunk
dwData.l
dwSize.l
EndStructure
Structure WaveFile
;Header
dwRiff.l
dwSize.l
dwWave.l
;Format
dwFormat.l
dwFormatSize.l
wFormatTag.w
wChannels.w
dwSamplesPerSec.l
dwAvgBytesPerSec.l
wBlockAlign.w
wBitsPerSample.w
;Data
dwData.l
dwDataSize.l
EndStructure
;******************************************
;* Déclaration des structures DirectSound *
;******************************************
Structure WaveFormatEx
wFormatTag.w
nChannels.w
nSamplesPerSec.l
nAvgBytesPerSec.l
nBlockAlign.w
wBitsPerSample.w
cbSize.w
EndStructure
Structure DSBufferDesc
dwSize.l
dwFlags.l
dwBufferBytes.l
dwReserved.l
*lpwfxFormat
guid3DAlgorithm.Guid
EndStructure
Structure DirectSoundWave Extends WaveFile
*lpDataSection.l
;DirectSound
Sound.IDirectSoundBuffer8
PrimaryBuffer.IDirectSoundBuffer
DirectSound8.IDirectSound8
EndStructure
;***********************************
;* Déclaration des constantes Wave *
;***********************************
#Wave_Chunk_Riff = 'FFIR'
#Wave_Chunk_Wave = 'EVAW'
#Wave_Chunk_Format = ' tmf'
#Wave_Chunk_Data = 'atad'
#Wave_Sample_Raw = %0000
#Wave_Sample_Percent = %0001
#Wave_Sample_Left = %0010
#Wave_Sample_Right = %0100
#Wave_Frequency_Min = 1000
#Wave_Frequency_Max = 100000
Enumeration 0
#Wave_Offset_Sample
#Wave_Offset_Time
EndEnumeration
Enumeration 1
#Wave_Channels_Mono
#Wave_Channels_Stereo
EndEnumeration
Enumeration 1
#Wave_Depth_8bits
#Wave_Depth_16bits
#Wave_Depth_24bits
#Wave_Depth_32bits
EndEnumeration
#Wave_Depth_Max = #PB_Compiler_EnumerationValue - 1
;******************************************
;* Déclaration des constantes DirectSound *
;******************************************
#DS_OK = 0
Enumeration 1
#DSSCL_Normal
#DSSCL_Priority
#DSSCL_Exclusive
#DSSCL_WritePrimary
EndEnumeration
Enumeration 1
#DSBPlay_Looping
#DSBLock_EntireBuffer
EndEnumeration
#DSBCaps_LocSoftware = $08
#DSBCaps_CtrlFrequency = $20
#DSBCaps_CtrlPan = $40
#DSBCaps_CtrlVolume = $80
DataSection
IID_DirectSoundBuffer8:
Data.l $6825A449
Data.w $7524, $4D82
Data.b $92, $0F, $50, $E3
Data.b $6A, $B3, $AB, $1E
EndDataSection
;**************************************
;* Déclaration des variables globales *
;**************************************
Global DS_Library
;**********************************
;* Déclaration des fonctions Wave *
;**********************************
Declare.l InitWave()
Declare.l CatchWave (WindowID.l, *wfh.WaveFileHeader, Length.l)
Declare.l IsWave (*dsw.DirectSoundWave)
Declare.l LoadWave (WindowID.l, Location.s)
Declare.l SaveWave (*dsw.DirectSoundWave, Location.s)
Declare.l FreeWave (*dsw.DirectSoundWave)
Declare.l CloneWave (WindowID.l, *dsw.DirectSoundWave)
Declare.l CreateWave(WindowID.l, Depth.l, Frequency.l, Samples.l, Channels.l)
Declare.l WaveChannels (*dsw.DirectSoundWave)
Declare.l WaveFrequency (*dsw.DirectSoundWave)
Declare.l WaveDepth (*dsw.DirectSoundWave)
Declare.l WaveSamples (*dsw.DirectSoundWave)
Declare.l WaveLength (*dsw.DirectSoundWave)
Declare.l WaveSaturation (*dsw.DirectSoundWave)
Declare.l WaveSamplingRate(*dsw.DirectSoundWave)
Declare.l WaveSample (*dsw.DirectSoundWave, Position.l, Mode.l)
Declare.l WaveSamplePos (*dsw.DirectSoundWave, Time.l)
Declare.l PlayWave (*dsw.DirectSoundWave, Looping.l)
Declare.l StopWave (*dsw.DirectSoundWave)
Declare.l PauseWave (*dsw.DirectSoundWave)
Declare.l ResumeWave (*dsw.DirectSoundWave)
Declare.l ReverseWave (*dsw.DirectSoundWave)
Declare.l ConvertWave (*dsw.DirectSoundWave, NewValue.l, Type.l)
Declare.l ConvertWaveDepth(WindowID.l, *dsw.DirectSoundWave, Depth)
Declare.l MixWaves (*dsw1.DirectSoundWave, *dsw2.DirectSoundWave, Offset.l, Mode.l)
;*********************************
;* Définition des fonctions Wave *
;*********************************
Procedure.l InitWave()
If DS_Library = #Null Or IsLibrary(DS_Library) = #False
DS_Library = OpenLibrary(#PB_Any, "dsound.dll")
EndIf
ProcedureReturn DS_Library
EndProcedure
Procedure.l CatchWave(WindowID.l, *wfh.WaveFileHeader, Length)
Protected Catch.l, ids8.IDirectSound8, dsbd.DSBufferDesc, idsb.IDirectSoundBuffer
Protected wfx.WaveFormatEx, *wfc.WaveFormatChunk, *wdc.WaveDataChunk, *wf.WaveFile
Protected *wc.WaveChunk, Offset.l, HasFormat.l, HasData.l, BytesPerSample.l
Protected WaveSize.l, tidsb.IDirectSoundBuffer, idsb8.IDirectSoundBuffer8
Protected lpWrite.l, dwLength.l, *dsw.DirectSoundWave
If InitWave()
If CallFunction(DS_Library, "DirectSoundCreate8", #Null, @ids8, #Null) = #DS_OK
If ids8\SetCooperativeLevel(WindowID, #DSSCL_Normal) = #DS_OK
;-a corriger
dsbd\dwSize = SizeOf(DSBufferDesc)
dsbd\dwFlags = 1
dsbd\dwBufferBytes = #Null
dsbd\lpwfxFormat = #Null
;Extraction des chunks
If ids8\CreateSoundBuffer(dsbd, @idsb, #Null) = #DS_OK
If *wfh\dwRiff = #Wave_Chunk_Riff And *wfh\dwWave = #Wave_Chunk_Wave
If *wfh\dwSize + OffsetOf(WaveFileHeader\dwWave) = Length
Offset = SizeOf(WaveFileHeader)
*wc = *wfh + Offset
Offset + SizeOf(WaveChunk)
If Length - Offset < *wc\dwSize
Offset = Length
EndIf
While Offset < Length
If HasFormat = #False And *wc\dwTag = #Wave_Chunk_Format
*wfc = *wc
If *wfc\dwSize + SizeOf(WaveChunk) > SizeOf(WaveFormatChunk)
*wfc\dwSize = SizeOf(WaveFormatChunk) - SizeOf(WaveChunk)
EndIf
BytesPerSample = *wfc\wBitsPerSample >> 3
If *wfc\wFormatTag = #Wave_Format_PCM
If BytesPerSample >= 1 And BytesPerSample <= 4
If *wfc\wChannels = #Wave_Channels_Mono Or *wfc\wChannels = #Wave_Channels_Stereo
If *wfc\dwSamplesPerSec >= #Wave_Frequency_Min And *wfc\dwSamplesPerSec <= #Wave_Frequency_Max
HasFormat = #True
;Recalcule les données calculées par sécurité
*wfc\wBlockAlign = BytesPerSample * *wfc\wChannels
*wfc\dwAvgBytesPerSec = *wfc\dwSamplesPerSec * *wfc\wBlockAlign
EndIf
EndIf
EndIf
EndIf
ElseIf HasData = #False And *wc\dwTag = #Wave_Chunk_Data
HasData = #True
*wdc = *wc
EndIf
;lit le chunk suivant
Offset + *wc\dwSize + SizeOf(WaveChunk)
*wc + *wc\dwSize + SizeOf(WaveChunk)
If Length - Offset < *wc\dwSize
Offset = Length
EndIf
Wend
;On ne garde que les chunk Format et Data
If HasFormat And HasData
WaveSize = SizeOf(WaveFileHeader) + SizeOf(WaveFormatChunk)
WaveSize + SizeOf(WaveDataChunk) + *wdc\dwSize
*wf = AllocateMemory(WaveSize)
If *wf
;Remplit la zone de mémoire allouée
*wf\dwRiff = #Wave_Chunk_Riff
*wf\dwSize = WaveSize - OffsetOf(WaveFileHeader\dwWave)
*wf\dwWave = #Wave_Chunk_Wave
CopyMemory( *wfc, *wf+SizeOf(WaveFileHeader), SizeOf(WaveFormatChunk) )
CopyMemory( *wdc, *wf+SizeOf(WaveFileHeader)+SizeOf(WaveFormatChunk), *wdc\dwSize+SizeOf(WaveChunk) )
;Copie le chunk Format
CopyMemory( *wfc+SizeOf(WaveChunk), wfx, SizeOf(WaveFormatChunk)-SizeOf(WaveChunk) )
dsbd\dwFlags = #DSBCaps_LocSoftware|#DSBCaps_CtrlFrequency|#DSBCaps_CtrlPan|#DSBCaps_CtrlVolume
dsbd\dwBufferBytes = *wdc\dwSize
dsbd\lpwfxFormat = wfx
If ids8\CreateSoundBuffer(dsbd, @tidsb, #Null) = #DS_OK
Debug "oké"
tidsb\QueryInterface(?IID_DirectSoundBuffer8, @idsb8)
tidsb\Release()
If idsb8
If idsb8\Lock(#Null, #Null, @lpWrite, @dwLength, #Null, #Null, #DSBLock_EntireBuffer) = #DS_OK
CopyMemory(*wf+SizeOf(WaveFile), lpWrite, dwLength)
idsb8\UnLock(lpWrite, dwLength, #Null, #Null)
*dsw = AllocateMemory( SizeOf(DirectSoundWave) )
If *dsw
CopyMemory( *wf, *dsw, SizeOf(WaveFile) )
*dsw\lpDataSection = lpWrite
*dsw\Sound = idsb8
*dsw\PrimaryBuffer = idsb
*dsw\DirectSound8 = ids8
Catch = *dsw
Else
idsb\Release()
ids8\Release()
idsb8\Release()
EndIf
EndIf
Else
idsb\Release()
ids8\Release()
EndIf
Else
idsb\Release()
ids8\Release()
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
ProcedureReturn Catch
EndProcedure
Procedure.l IsWave(*dsw.DirectSoundWave)
Protected IsWave.l
If InitWave()
If *dsw
If *dsw\dwRiff = #Wave_Chunk_Riff And *dsw\dwWave = #Wave_Chunk_Wave
If *dsw\dwFormat = #Wave_Chunk_Format And *dsw\dwData = #Wave_Chunk_Data
IsWave = #True
EndIf
EndIf
EndIf
EndIf
ProcedureReturn IsWave
EndProcedure
Procedure.l LoadWave(WindowID.l, Location.s)
Protected Load.l, File.l, *ptr.l
File = ReadFile(#PB_Any, Location)
If File And Lof() > SizeOf(WaveFile)
*ptr = AllocateMemory( Lof() )
If *ptr
ReadData( *ptr, Lof() )
Load = CatchWave( WindowID.l, *ptr, Lof() )
FreeMemory(*ptr)
EndIf
CloseFile(File)
EndIf
ProcedureReturn Load
EndProcedure
Procedure.l SaveWave(*dsw.DirectSoundWave, Location.s)
Protected Save.l, File.l
If InitWave() And IsWave(*dsw)
File = CreateFile(#PB_Any, Location)
If File
Save = #True
WriteData( *dsw, SizeOf(WaveFile) )
WriteData(*dsw\lpDataSection, *dsw\dwDataSize)
CloseFile(File)
EndIf
EndIf
ProcedureReturn Save
EndProcedure
Procedure.l FreeWave(*dsw.DirectSoundWave)
Protected Free.l
If InitWave() And IsWave(*dsw)
;*dsw\Sound\Release()
;*dsw\PrimaryBuffer\Release()
;*dsw\DirectSound8\Release()
Free = FreeMemory(*dsw)
EndIf
ProcedureReturn Free
EndProcedure
Procedure.l CloneWave(WindowID.l, *dsw.DirectSoundWave)
Protected Clone.l, *wf.WaveFile, Length.l
If InitWave() And IsWave(*dsw)
Length = *dsw\dwSize+OffsetOf(WaveFile\dwWave)
*wf = AllocateMemory(Length)
If *wf
CopyMemory( *dsw, *wf, SizeOf(WaveFile) )
CopyMemory(*dsw\lpDataSection, *wf+SizeOf(WaveFile), *dsw\dwDataSize)
Clone = CatchWave(WindowID, *wf, Length)
FreeMemory(*wf)
EndIf
EndIf
ProcedureReturn Clone
EndProcedure
Procedure.l CreateWave(WindowID.l, Depth.l, Frequency.l, Samples.l, Channels.l)
Protected *wf.WaveFile, *dsw.DirectSoundWave
Protected BytesPerSample.l, BlockAlign.l, Size.l
If InitWave()
BytesPerSample = Depth >> 3
If BytesPerSample >= 1 And BytesPerSample <= 4
If Frequency >= #Wave_Frequency_Min And Frequency <= #Wave_Frequency_Max
If Channels = #Wave_Channels_Mono Or Channels = #Wave_Channels_Stereo
If Samples >= 0
BlockAlign = BytesPerSample * Channels
Size = SizeOf(WaveFile) + BlockAlign * Samples
*wf = AllocateMemory(Size)
If *wf
*wf\dwRiff = #Wave_Chunk_Riff
*wf\dwSize = Size - SizeOf(WaveChunk)
*wf\dwWave = #Wave_Chunk_Wave
*wf\dwFormat = #Wave_Chunk_Format
*wf\dwFormatSize = SizeOf(WaveFormatChunk) - SizeOf(WaveChunk)
*wf\wFormatTag = #WAVE_FORMAT_PCM
*wf\wChannels = Channels
*wf\dwSamplesPerSec = Frequency
*wf\dwAvgBytesPerSec = Frequency * BlockAlign
*wf\wBlockAlign = BlockAlign
*wf\wBitsPerSample = Depth
*wf\dwData = #Wave_Chunk_Data
*wf\dwDataSize = BlockAlign * Samples
*dsw = CatchWave(WindowID, *wf, Size)
FreeMemory(*wf)
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
ProcedureReturn *dsw
EndProcedure
Procedure.l WaveChannels(*dsw.DirectSoundWave)
Protected Channels.l
If InitWave() And IsWave(*dsw)
Channels = *dsw\wChannels
EndIf
ProcedureReturn Channels
EndProcedure
Procedure.l WaveFrequency(*dsw.DirectSoundWave)
Protected Frequency.l
If InitWave() And IsWave(*dsw)
Frequency = *dsw\dwSamplesPerSec
EndIf
ProcedureReturn Frequency
EndProcedure
Procedure.l WaveDepth(*dsw.DirectSoundWave)
Protected Frequency.l
If InitWave() And IsWave(*dsw)
Frequency = *dsw\wBitsPerSample
EndIf
ProcedureReturn Frequency
EndProcedure
Procedure.l WaveSamples(*dsw.DirectSoundWave)
Protected Samples.l
If InitWave() And IsWave(*dsw)
Samples = *dsw\dwDataSize / *dsw\wBlockAlign
EndIf
ProcedureReturn Samples
EndProcedure
Procedure.l WaveLength(*dsw.DirectSoundWave)
Protected Length.l
If InitWave() And IsWave(*dsw)
Length = (1000 * *dsw\dwDataSize) / (*dsw\wBlockAlign * *dsw\dwSamplesPerSec)
EndIf
ProcedureReturn Length
EndProcedure
Procedure.l WaveSaturation(*dsw.DirectSoundWave)
Protected Saturation.l, BytesPerSample.l, i.l
If InitWave() And IsWave(*dsw)
i = 0
BytesPerSample = *dsw\wBitsPerSample >> 3
While i < BytesPerSample
Saturation + $FF << (i << 3)
i + 1
Wend
SHR Saturation, 1
EndIf
ProcedureReturn Saturation
EndProcedure
Procedure.l WaveSamplingRate(*dsw.DirectSoundWave)
Protected Rate.l
If InitWave() And IsWave(*dsw)
Rate = *dsw\dwAvgBytesPerSec
EndIf
ProcedureReturn Rate
EndProcedure
Procedure.l WaveSample(*dsw.DirectSoundWave, Position.l, Mode.l)
Protected Sample.l, Left.l, Right.l, Saturation.l, BytesPerSample.l, *ptr.l, i.l
If InitWave() And IsWave(*dsw) And Position >= 0 And Position < WaveSamples(*dsw)
BytesPerSample = *dsw\wBitsPerSample >> 3
*ptr = *dsw\lpDataSection + Position * *dsw\wBlockAlign
If *dsw\wChannels = #Wave_Channels_Mono
While i < BytesPerSample
Sample + PeekB(*ptr + i) << (i << 3)
i + 1
Wend
Else
While i < BytesPerSample
Left + PeekB(*ptr + i) << (i << 3)
Right + PeekB(*ptr + i + BytesPerSample) << (i << 3)
i + 1
Wend
If Mode & #Wave_Sample_Left
Right = Left
ElseIf Mode & #Wave_Sample_Right
Left = Right
EndIf
Sample = (Right + Left) >> 1
EndIf
If *dsw\wBitsPerSample = 8
If Sample < 0
Sample + 256
EndIf
Sample - 127
EndIf
If Mode & #Wave_Sample_Percent
Sample * 100.0 / WaveSaturation(*dsw)
EndIf
EndIf
ProcedureReturn Sample
EndProcedure
Procedure.l WaveSamplePos(*dsw.DirectSoundWave, Time.l)
Protected SamplePos.l, Length.l, fTime.f
Length = WaveLength(*dsw)
If InitWave() And IsWave(*dsw) And Time >=0 And Time < Length
fTime = Time
SamplePos = (WaveSamples(*dsw) * fTime) / Length
EndIf
ProcedureReturn SamplePos
EndProcedure
Procedure.l SetWavePosition(*dsw.DirectSoundWave, Position)
Protected Set.l
If InitWave() And IsWave(*dsw)
If Position >= 0 And Position <= WaveSamples(*dsw)
*dsw\Sound\SetCurrentPosition(Position)
EndIf
EndIf
ProcedureReturn Set
EndProcedure
Procedure.l PlayWave(*dsw.DirectSoundWave, Looping.l)
Protected Play.l
If InitWave() And IsWave(*dsw)
If Looping
Looping = #DSBPlay_Looping
EndIf
SetWavePosition(*dsw, 0)
*dsw\Sound\Play(#NULL, #NULL, #NULL)
Play = #TRUE
EndIf
ProcedureReturn Play
EndProcedure
Procedure.l StopWave(*dsw.DirectSoundWave)
Protected Stop.l
If InitWave() And IsWave(*dsw)
Stop = *dsw\Sound\Stop()
SetWavePosition(*dsw, 0)
EndIf
ProcedureReturn Stop
EndProcedure
Procedure.l ReverseWave(*dsw.DirectSoundWave)
Protected Reverse.l, MemStart.l, MemEnd.l, Position.l, Size.l
If InitWave() And IsWave(*dsw)
Size = *dsw\wBlockAlign
MemStart = *dsw\lpDataSection
MemEnd = MemStart + *dsw\dwDataSize - Size
Position = (WaveSamples(*dsw) >> 1) * Size
While Position >= 0
Swap(MemStart+Position, MemEnd-Position, Size)
Position - Size
Wend
Reverse = #TRUE
EndIf
ProcedureReturn Reverse
EndProcedure
Procedure.l ConvertWaveDepth(WindowID.l, *dsw.DirectSoundWave, Depth.l)
Protected *convert.DirectSoundWave, Ratio.f, BytesPerSample.l
Protected i.l, Sample.l, Samples.l, *p1.l, *p2.l, Mask.l
If InitWave() And IsWave(*dsw) And *dsw\wBitsPerSample <> Depth
If Depth > *dsw\wBitsPerSample
Mask = (1 << (Depth - *dsw\wBitsPerSample))
Ratio = Mask + 0.0
Else
Mask = (1 << (*dsw\wBitsPerSample - Depth))
Ratio = 1.0 / Mask
EndIf
Depth >> 3
BytesPerSample = *dsw\wBitsPerSample >> 3
If Depth >= 1 And Depth <= 4
*convert = CreateWave(WindowID, Depth << 3, *dsw\dwSamplesPerSec, WaveSamples(*dsw), *dsw\wChannels)
If *convert
;nombre d'échantillon à traiter
Samples = *dsw\dwDataSize / BytesPerSample
*p1 = *dsw\lpDataSection
*p2 = *convert\lpDataSection
While Samples > 0
;lecture du sample
i = 0
Sample = 0
While i < BytesPerSample
Sample + PeekB(*p1+i) << (i << 3)
i + 1
Wend
*p1 + BytesPerSample
;conversion du sample
If BytesPerSample = 1 ;le 8bits est non signé
If Sample < 0
Sample + 256
EndIf
Sample - 127
EndIf
Sample * Ratio
If Depth = 1 ;le 8bits est non signé
If Sample > 127
Sample = 127
EndIf
Sample + 127
EndIf
;écriture du nouveau sample
i = 0
While i < Depth
i << 3
Mask = $FF << i
Mask = (Mask & Sample) >> i
i >> 3
PokeB(*p2 + i, Mask)
i + 1
Wend
*p2 + Depth
Samples - 1
Wend
EndIf
EndIf
EndIf
ProcedureReturn *convert
EndProcedure
