Sto' ragionando su quale metodo sia il migliore per estrarre da un file audio la sua forma d'onda (al fine di visualizzarla e sovrapporci un cursore sopra durante la riproduzione).
Gstreamer potrebbe essere il partner ideale, e cercando un po' ho trovato un pezzo di codice C che potrebbe aiutare nell'operazione ...
https://github.com/erikd/sndfile-tools/blob/master/src/waveform.c
/*
** Copyright (C) 2007-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2012 Robin Gareus <robin@gareus.org>
** Copyright (C) 2013 driedfruit <driedfruit@mindloop.net>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 or version 3 of the
** License.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
** Generate a waveform as a PNG file from a given sound file.
*/
..... etc etc
fare anche una "visualizzazione" di tipo waveform come estenzione per gstreamer potrebbe essere un'opzione ......
qui' il termine waveform compare in piu' istanze ......
http://gstreamer.freedesktop.org/documentation/plugins.html
qualcuno suggerisce di utilizzare mmap per mappare il file in un'area di memoria (per velocizzare l'accesso): http://man7.org/linux/man-pages/man2/mmap.2.html
Ho cercato di trasportare in Gambas l'esempio in C presente in quella pagina:
Private Const _SC_PAGE_SIZE As Byte = 30
Private Const PROT_READ As Byte = 1 ' Data can be read
Private Const MAP_PRIVATE As Byte = 2 ' Changes are private
Private Const MAP_FAILED As Integer = -1 ' Return value of `mmap' in case of an error
Library "libc:6"
' long sysconf(int name)
' Restituisce il valore del parametro di sistema name.
Private Extern sysconf(name As Integer) As Long
' void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, __off_t __offset) __THROW
' Map addresses starting near ADDR and extending for LEN bytes.
Private Extern mmap(_addr As Pointer, _len As Integer, _prot As Integer, flags As Integer, _fd As Integer, off_t As Integer) As Pointer
Public Sub Main()
Dim percorsoFile As String
Dim fl As File
Dim addr As Pointer
Dim lungh_file, length, i As Integer
Dim offset, pa_offset As Long
Dim st As Stream
Dim b As Byte
percorsoFile = "/percorso/del/file/da/leggere"
lungh_file = Stat(percorsoFile).Size
offset = 8 ' numero d'indice 'esemplificativo' di partenza dei byte da leggere
length = 7 ' quantità 'esemplificativa' dei byte da leggere
fl = Open percorsoFile For Read
If IsNull(fl) Then Error.Raise("Impossibile aprire il file !")
pa_offset = offset And (Not (sysconf(_SC_PAGE_SIZE) - 1))
If offset >= lungh_file Then Error.Raise("Il valore della variabile 'offset' ha oltrepassato la fine del file !")
If length > 0 Then
If offset + length > lungh_file Then length = lungh_file - offset
Else
length = lungh_file - offset
Endif
addr = mmap(0, length + offset - pa_offset, PROT_READ, MAP_PRIVATE, fl.Handle, pa_offset)
If addr = MAP_FAILED Then Error.Raise("Errore alla funzione 'mmap()' !")
' Dereferenziamo il 'Puntatore' "addr" mediante i "Memory Stream":
st = Memory addr For Read
For i = 0 To length - 1
Seek #st, (offset - pa_offset) + i
Read #st, b
Print b, Chr(b)
Next
st.Close
fl.Close
End
In alternativa, si può trasformare quell'esempio in un una libreria esterna condivisa .so ;D
oppure utilizzare fdsink al posto di fakesink:
....e quindi quale strada hai scelto ?
... ho trovato un pezzo di codice C che potrebbe aiutare nell'operazione ...
https://github.com/erikd/sndfile-tools/blob/master/src/waveform.c
Ciao,
ho ripreso questo codice da te segnalato e ne ho creato una libreria esterna condivisa .so, che qui ti allego.
Circa l'uso, facendo l'esempio che poni questo file della libreria esterna nel percorso /tmp, mostro con un semplicissimo codice come va utilizzata in Gambas:
Library "/tmp/creaonda"
Private Extern Crea_Onda(i As Integer, param As String[]) As Integer
Private Extern usage_exit(uss As String[], status As Integer)
Public Sub Main()
Dim ss As String[] = ["Crea onda", "-b", "-c 1", "/percorso/del/file/audio.wav", "/percorso/dove/verrà/salvato/il file/immagine/dell'onda.png"]
Dim err As Integer
err = Crea_Onda(5, ss)
If err <> 0 Then Error.Raise("Errore nella realizzazione dell'immagine dell'onda audio !")
' Mostra contemporaneamente in console una breve guida sull'uso della libreria:
usage_exit(Null, 0)
Print "\n\n\nFile immagine: creato."
End
E' assolutamente necessario avere installata nel sistema la libreria di sndfile .
ah .. ecco .... era semplice ....
un bel problema ....
con un file WAV codificato opus (scaricato dal sito degli sviluppatori di opus codec) il sistema va' ...
dopo aver passato la path con un dialog chiamo questo form (MusicImporter) di editing audio e nel form_open
Public Sub Form_Open()
Dim hImage As Picture
WaveForm.MusicFilePath = MusicImporter.Tag
If Exist(MusicImporter.Tag & ".png") = False Then WaveForm.Main
hImage = Picture.Load(MusicImporter.Tag & ".png")
DrawingArea_WaveForm.Clear
DrawingArea_WaveForm.Width = hImage.Width
DrawingArea_WaveForm.Height = hImage.Height
DrawingArea_WaveForm.BackGround = Color.Green
Draw.Begin(DrawingArea_WaveForm)
Draw.Picture(hImage, 0, 0, 800, 200)
Draw.End
End
nel modulo WaveForm (che hai codiifcato tu), ho aggiunto una public per parametrizzare la path del file audio
Public MusicFilePath As String
e nel main del waveform ho seguito di conseguenza:
Public Sub Main()
Dim rend As New RENDER
Dim percorsoFile As String
percorsoFile = MusicFilePath ' Il file audio (wav o ogg) dal quale creare la forma d'onda
With rend
.sndfilepath = percorsoFile
.pngfilepath = percorsoFile & ".png" ' Il percorso del futuro file .png
.filename = File.Name(percorsoFile) ' Il solo nome del file comprensivo di estensione
etc etc etc
e' carino .. ma il limite degli mp3 e' tosto .....