Seite 1 von 2

Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 18:06
von rowo
Hallo liebe Purebasic Programmierer. Ich bin vor einiger Zeit auf Purebasic gestoßen und würde mich mittlerweile nicht mehr ganz als blutiger Anfänger bezeichnen. Aber aktuell beiße ich mir die Zähne an einer Sache aus. Ich habe hier rund 500 MB an WAV Dateien, über 800 ganz kurze Schnipsel von je 5-6 Sekunden. Die möchte ich in eine SQLite Datenbank packen und von da aufrufen und abspielen. Also nicht aus dem Dateisystem heraus z. B. C:\xxx\1.wav sondern als BLOB aus der Datenbank laden und dann abspielen lassen.
Ich habe mich in diese Anleitung eingearbeitet, nur gehts da um Bilder, die als BLOB gespeichert werden. http://forums.purebasic.com/german/view ... =9&t=24643
Irgendwie komme ich nicht weiter. Falls hier jemand eine Idee hat oder mir ein paar Tipps geben könnte...Vielen Dank.

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 18:35
von RSBasic
Soweit ich weiß laut Erfahrungswerte von Leuten sollte man große Datenmenge nicht in die Datenbank auslagern, weil erstens die Datenbank sehr groß wird (was logisch ist) und zweitens weil die Performance der Datenbank sich verschlechtert. Ich meine, mal gelesen zu haben, dass man die Dateien lieber auf der Festplatte lassen soll, die in der Datenbank als Verweis eingetragen werden.

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 18:36
von ccode_new
Hallo rowo!

Hier einmal ein Beispiel:

Code: Alles auswählen

Procedure DateiHinzufuegen(aDatei.s)
  Protected *mem, size, sql.s, id_name.s, fstring
  If FileSize(aDatei) > 0 And FileSize(aDatei) < 8000000
    If ReadFile(0, aDatei)
      size = Lof(0)
      If size
        *mem = AllocateMemory(size)
        If *mem
          ReadData(0, *mem, size)
          SetDatabaseBlob(#DeineDB, 0, *mem, size)
          sql = "UPDATE tabelle SET "
          sql + "extdata = ? ,"
          sql + "extname = '" + GetFilePart(aDatei) + "' "
          sql + "WHERE name = '" + GetFilePart(aDatei) +"'"        
          If Not DatabaseUpdate(#DeineDB, sql) 
            Debug DatabaseError()
          Else
            MessageRequester("Hinweis", "Die Datei wurde der Datenbank hinzugefügt!", #PB_MessageRequester_Info)
          EndIf
          FreeMemory(*mem)
        EndIf
      EndIf
      CloseFile(0)
    EndIf
  ElseIf FileSize(aDatei) > 0 And FileSize(aDatei) > 8000000
    brechnung.d = FileSize(aDatei)/1000000
    MessageRequester("Fehler", "Die Datei darf 8 Mbyte nicht übersteigen."+Chr(13)+Chr(13)+"Ihre ausgewählte Datei ist "+StrD(brechnung)+" Mbyte groß.", #PB_MessageRequester_Error)
  ElseIf FileSize(aDatei) = -1
    MessageRequester("Fehler", "keine Datei ?", #PB_MessageRequester_Error)
  EndIf
EndIf
EndProcedure

Procedure DateiExtract(id_name.i, id_extFile.i, sel_name.s)
  Protected.s SQL, name, extname
  Protected *mem, size, fstring
  
  SQL = "SELECT * FROM tabelle"
  
  If DatabaseQuery(#DeineDB, SQL)
    While NextDatabaseRow(#DeineDB)   ; alle Einträge durchlaufen
      name = GetDatabaseString(#DeineDB, 1)
      If sel_name = name
        extname = GetDatabaseString(#DeineDB, id_name)
        
        saveFile$ = SaveFileRequester("Datei extrahieren", extname, "*.*", 0)
        
        size = DatabaseColumnSize(#DeineDB, id_extFile)
        
        If Not CheckDatabaseNull(#DeineDB, id_extFile)
          *mem = AllocateMemory(size)
          If *mem
            ; Mit GetDatabaseBlob laden wir nun die Daten in unseren Speicher.
            If GetDatabaseBlob(#DeineDB, id_extFile, *mem, size)
              If CreateFile(0, saveFile$)
                WriteData(0, *mem, size)    
                CloseFile(0)
                MessageRequester("Hinweis", "Die Datei wurde erfolgreich extrahiert.", #PB_MessageRequester_Info)
              Else
                Debug "Konnte die Datei nicht erstellen!"
                MessageRequester("Fehler", "Die Datei konnte nicht extrahiert werden.", #PB_MessageRequester_Error)
              EndIf               
              FreeMemory(*mem)
            EndIf
          EndIf
        EndIf
        Break
      EndIf
    Wend
    FinishDatabaseQuery(#DeineDB)
  EndIf
EndIf
EndProcedure

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 18:39
von rowo
Hallo. Die Datenbank wird sich nicht vergrößern und es werden keine neuen WAV Dateien hinzugefügt. Nur die vorhandenen sollen da rein und von da aufgerufen werden..

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 18:43
von rowo
Hallo, vielen Dank für die schnelle Antwort. Ich werde mir dein Beispiel gleich mal anschauen und vielleicht ist das die Lösung.

ccode_new hat geschrieben:Hallo rowo!

Hier einmal ein Beispiel:

Code: Alles auswählen

Procedure DateiHinzufuegen(aDatei.s)
  Protected *mem, size, sql.s, id_name.s, fstring
  If FileSize(aDatei) > 0 And FileSize(aDatei) < 8000000
    If ReadFile(0, aDatei)
      size = Lof(0)
      If size
        *mem = AllocateMemory(size)
        If *mem
          ReadData(0, *mem, size)
          SetDatabaseBlob(#DeineDB, 0, *mem, size)
          sql = "UPDATE tabelle SET "
          sql + "extdata = ? ,"
          sql + "extname = '" + GetFilePart(aDatei) + "' "
          sql + "WHERE name = '" + GetFilePart(aDatei) +"'"        
          If Not DatabaseUpdate(#DeineDB, sql) 
            Debug DatabaseError()
          Else
            MessageRequester("Hinweis", "Die Datei wurde der Datenbank hinzugefügt!", #PB_MessageRequester_Info)
          EndIf
          FreeMemory(*mem)
        EndIf
      EndIf
      CloseFile(0)
    EndIf
  ElseIf FileSize(aDatei) > 0 And FileSize(aDatei) > 8000000
    brechnung.d = FileSize(aDatei)/1000000
    MessageRequester("Fehler", "Die Datei darf 8 Mbyte nicht übersteigen."+Chr(13)+Chr(13)+"Ihre ausgewählte Datei ist "+StrD(brechnung)+" Mbyte groß.", #PB_MessageRequester_Error)
  ElseIf FileSize(aDatei) = -1
    MessageRequester("Fehler", "keine Datei ?", #PB_MessageRequester_Error)
  EndIf
EndIf
EndProcedure

Procedure DateiExtract(id_name.i, id_extFile.i, sel_name.s)
  Protected.s SQL, name, extname
  Protected *mem, size, fstring
  
  SQL = "SELECT * FROM tabelle"
  
  If DatabaseQuery(#DeineDB, SQL)
    While NextDatabaseRow(#DeineDB)   ; alle Einträge durchlaufen
      name = GetDatabaseString(#DeineDB, 1)
      If sel_name = name
        extname = GetDatabaseString(#DeineDB, id_name)
        
        saveFile$ = SaveFileRequester("Datei extrahieren", extname, "*.*", 0)
        
        size = DatabaseColumnSize(#DeineDB, id_extFile)
        
        If Not CheckDatabaseNull(#DeineDB, id_extFile)
          *mem = AllocateMemory(size)
          If *mem
            ; Mit GetDatabaseBlob laden wir nun die Daten in unseren Speicher.
            If GetDatabaseBlob(#DeineDB, id_extFile, *mem, size)
              If CreateFile(0, saveFile$)
                WriteData(0, *mem, size)    
                CloseFile(0)
                MessageRequester("Hinweis", "Die Datei wurde erfolgreich extrahiert.", #PB_MessageRequester_Info)
              Else
                Debug "Konnte die Datei nicht erstellen!"
                MessageRequester("Fehler", "Die Datei konnte nicht extrahiert werden.", #PB_MessageRequester_Error)
              EndIf               
              FreeMemory(*mem)
            EndIf
          EndIf
        EndIf
        Break
      EndIf
    Wend
    FinishDatabaseQuery(#DeineDB)
  EndIf
EndIf
EndProcedure

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 19:02
von Bisonte
rowo hat geschrieben:Ich habe mich in diese Anleitung eingearbeitet, nur gehts da um Bilder, die als BLOB gespeichert werden. http://forums.purebasic.com/german/view ... =9&t=24643
Irgendwie komme ich nicht weiter. Falls hier jemand eine Idee hat oder mir ein paar Tipps geben könnte...Vielen Dank.
Hallo. Erstmal Top! Du hast das in meinen Augen beste Einstiegstutorial für SQLite gefunden ;)

Wenn dir die Sache mit den Blobs als Bildern absolut klar ist, dann sollte das mit WAV Dateien kein Problem darstellen.
Beides sind "nur" Binärdateien. Der einzige Unterschied : CatchImage wird durch CatchSound ersetzt. Das wars im Grunde schon.

Allerdings kann ich RSBasic nur zustimmen. Eine DB aus ca. 800 Dateien die gesamt eine Grösse von ca 500MB hat, ist schon hart
an der Grenze. Die Geschwindigkeit der DB wird extrem darunter leiden. Ausserdem ist es eine grosse Datei... die noch etwas grösser
wird, weil mit Sicherheit noch einiges dazugespeichert werden soll, und SQLite auch noch ein wenig Verwaltungsanhang besitzt.

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 19:19
von rowo
Bisonte hat geschrieben:
rowo hat geschrieben:Ich habe mich in diese Anleitung eingearbeitet, nur gehts da um Bilder, die als BLOB gespeichert werden. http://forums.purebasic.com/german/view ... =9&t=24643
Irgendwie komme ich nicht weiter. Falls hier jemand eine Idee hat oder mir ein paar Tipps geben könnte...Vielen Dank.
Hallo. Erstmal Top! Du hast das in meinen Augen beste Einstiegstutorial für SQLite gefunden ;)

Wenn dir die Sache mit den Blobs als Bildern absolut klar ist, dann sollte das mit WAV Dateien kein Problem darstellen.
Beides sind "nur" Binärdateien. Der einzige Unterschied : CatchImage wird durch CatchSound ersetzt. Das wars im Grunde schon.

Allerdings kann ich RSBasic nur zustimmen. Eine DB aus ca. 800 Dateien die gesamt eine Grösse von ca 500MB hat, ist schon hart
an der Grenze. Die Geschwindigkeit der DB wird extrem darunter leiden. Ausserdem ist es eine grosse Datei... die noch etwas grösser
wird, weil mit Sicherheit noch einiges dazugespeichert werden soll, und SQLite auch noch ein wenig Verwaltungsanhang besitzt.
Hallo, danke für die schnelle Antwort. Die Waves bringe ich nun in die Datenbank. Allerdings bekomme ich beim Auslesen der Daten mit CatchSound den Fehler: ERROR Das angegebene #Sound ist nicht initialisiert. Hier mein Code... :roll:

Code: Alles auswählen

Procedure SpieleWav(id)
  If InitSound() = 0 
    MessageRequester("Fehler", "Fehler beim Initialisieren des Sounds!") 
    ProcedureReturn 
  EndIf 
  
  Protected size, *mem
  
  If DatabaseQuery(#DBAudio, "SELECT * FROM Waves WHERE Wid = " + Str(id))
    NextDatabaseRow(#DBAudio)
    
    size = DatabaseColumnSize(#DBAudio, AudioData)
    *mem = AllocateMemory(size)
    If *mem
      If GetDatabaseBlob(#DBAudio, AudioData, *mem, size)
        CatchSound(0, *mem)
        PlaySound (0)
      EndIf
      FreeMemory(*mem)
    EndIf
    FinishDatabaseQuery(#DBAudio)
  Else
    Debug DatabaseError()
  EndIf
  FreeSound(0)
EndProcedure

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 19:24
von ts-soft
Ohne speichern und CatchSound geht es unter Windows ungefähr so:

Code: Alles auswählen

If GetDatabaseBlob(#DeineDB, id_extFile, *mem, size)
  PlaySound_(*mem, 0, #SND_MEMORY)
  FreeMemory(*mem)
EndIf

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 19:26
von Bisonte
eine Abfrage nach "CatchSound()", ob der Sound initialisiert ist, wäre sinnvoll.

Code: Alles auswählen

; Wichtiger Bestandteil. Wenn fehlgeschlagen macht das Programm keinen weiteren Sinn ?
If InitSound() = 0 ; Sollte man möglichst nur einmal aufrufen...
  MessageRequester("Fehler", "Fehler beim Initialisieren des Sounds!")
  End
EndIf

Procedure SpieleWav(id)

  Protected size, *mem, Sound
  
  If DatabaseQuery(#DBAudio, "SELECT * FROM Waves WHERE Wid = " + Str(id))
    
    NextDatabaseRow(#DBAudio)
    
    size = DatabaseColumnSize(#DBAudio, AudioData)
    *mem = AllocateMemory(size)
    
    If *mem
      If GetDatabaseBlob(#DBAudio, AudioData, *mem, size)
        Sound = CatchSound(#PB_Any, *mem, size)
        If IsSound(Sound) ; Ist der Sound korrekt initialisiert ?
          PlaySound (Sound)          
        EndIf
      EndIf
      FreeMemory(*mem)
    EndIf
    FinishDatabaseQuery(#DBAudio)
  Else
    Debug DatabaseError()
  EndIf
  
  If IsSound(Sound) ; Ist der Sound korrekt initialisiert ?
    FreeSound(Sound)
  EndIf
  
EndProcedure 

Re: Wave Dateien in SQLite Datenbank

Verfasst: 28.12.2017 20:40
von rowo
Hallo, dein Code funktioniert. Vielen Dank schon mal. Nur noch ein Problem: Wie kann ich da die Lautstärke ändern? Wenn ich SoundVolume nehme, bekomme ich einen Fehler.
ts-soft hat geschrieben:Ohne speichern und CatchSound geht es unter Windows ungefähr so:

Code: Alles auswählen

If GetDatabaseBlob(#DeineDB, id_extFile, *mem, size)
  PlaySound_(*mem, 0, #SND_MEMORY)
  FreeMemory(*mem)
EndIf