Bass.dll - Wiedergabe eines Teils der Source

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Bass.dll - Wiedergabe eines Teils der Source

    Moin Leute,
    ich baue mir gerade einen kleinen Wave-Editor und möchte ausschließlich den gerade in Bearbeitung befindlichen Ausschnitt wieder geben.
    Wenn ich der Beschreibung vertraue, sollte dies funktionieren:

    C#-Quellcode

    1. /// <summary>
    2. /// Starten der Wiedergabe
    3. /// </summary>
    4. /// <param name="startTime">in Sekunden</param>
    5. /// <param name="endTime">in Sekunden</param>
    6. public static void Play(double startTime, double endTime)
    7. {
    8. long offset = (long)(startTime * Audio.ByteRate);
    9. long length = (long)((endTime - startTime) * Audio.ByteRate);
    10. Audio.Channel = Bass.BASS_StreamCreateFile(Audio.FileToPlay, offset, length, 0);
    11. Bass.BASS_ChannelPlay(Audio.Channel, false);
    12. }
    Laut Beschreibung sind offset und length Start und Dauer in Bytes, Audio.ByteRate ist der entsprechende Wert aus dem Wave-Header (176400).
    Leider wird entweder die gesamte Datei abgespielt oder gar nichts.

    Alle gefundenen Beispiele haben da 0 als Parameter:

    C#-Quellcode

    1. Bass.BASS_StreamCreateFile(Audio.FileToPlay, 0, 0, 0);


    Hat jemand von Euch schon mal Ausschnitt-Wiedergabe gearbeitet?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich werde mir das mal anschauen und dir eine Lösung geben, aber du könntest auch mit BASS_ChannelSetPosition die Postion setzen(aufs Byte genau), dazu BASS_ChannelSetSync nutzen um informiert zu werden wenn der Channel eine bestimmte Position erreicht hat(type BASS_SYNC_POS) und den Stream dann stoppen

    bass.radio42.com/help/html/80c…02e-14e6-26e17e3c98a4.htm
    bass.radio42.com/help/html/b30…621-6b9c-2304b4dfe02c.htm

    Nicht so fein, aber ich schau mal nach einer besseren Lösung, ich kenn die BASS recht gut und denke ich werde was gutes finden. Evtl. ist nur eine weitere Option beim erstellen des Streams.


    edit @RodFromGermany
    Ich musste jetzt auch erstmal überlegen woran das gescheitert sein könnte, gut das ich mich mit Audio schon näher auseinander gesetzt hab.

    Also ich sehe du hast Zeit * ByteRate, wenn ByteRate = Abtastrate * AnzahlKanäle * (Bittiefe / 8) ist sollte es passen, tut es ja nicht, also scheint da der Hund begraben zu liegen. Du hattest falsche Werte.

    Ich hab das so erfolgreich getestet:

    C#-Quellcode

    1. int dummy = Bass.BASS_StreamCreateFile(path, 0, 0, 0);
    2. BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(dummy);
    3. if(info != null)
    4. {
    5. int depth = 16;
    6. if(info.Is32bit)
    7. {
    8. depth = 32;
    9. }
    10. if(info.Is8bit)
    11. {
    12. depth = 8;
    13. }
    14. // also richtig ist, AnzahlBytes / (BitTiefe / 8) / Anzahl Kanäle
    15. long startPos = Bass.BASS_ChannelSeconds2Bytes(dummy, 10.0) / (depth / 8) / info.chans;
    16. long lenght = Bass.BASS_ChannelSeconds2Bytes(dummy, 1.0) / (depth / 8) / info.chans;
    17. stream = Bass.BASS_StreamCreateFile(path, startPos, lenght, 0);
    18. if (stream != 0)
    19. {
    20. Bass.BASS_ChannelPlay(stream, false);
    21. }
    22. else
    23. {
    24. MessageBox.Show(Bass.BASS_ErrorGetCode().ToString());
    25. }
    26. }


    Ich denke das ist es was du brauchst.

    Aber kann man noch verbessern, wenn man den Stream anstatt mit 0 mit BASSFlag.BASS_SAMPLE_FLOAT erstellt ist der 32 Bit tief, so spart man sich die Abfragen mit der Bittiefe. BASS_StreamCreateFile(path, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT);

    C#-Quellcode

    1. int dummy = Bass.BASS_StreamCreateFile(path, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT);
    2. BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(dummy);
    3. if(info != null)
    4. {
    5. // hier nun einfach AnzahlBytes / 4 / Anzahl Kanäle
    6. long startPos = Bass.BASS_ChannelSeconds2Bytes(dummy, 10.0) / 4 / info.chans;
    7. long lenght = Bass.BASS_ChannelSeconds2Bytes(dummy, 1.0) / 4 / info.chans;
    8. stream = Bass.BASS_StreamCreateFile(path, startPos, lenght, BASSFlag.BASS_SAMPLE_FLOAT);
    9. if (stream != 0)
    10. {
    11. Bass.BASS_ChannelPlay(stream, false);
    12. }
    13. else
    14. {
    15. MessageBox.Show(Bass.BASS_ErrorGetCode().ToString());
    16. }
    17. }


    Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von „Takafusa“ ()

    @Takafusa Danke für Deine Bemühungen.
    Es kommt immer BASS_ERROR_FILEFORM zurück, die Datei gefällt ihm irgendwie nicht.
    Egal ob BASSFlag.BASS_SAMPLE_FLOAT oder 0, die Position und Länge ist stets dieselbe, wie bei meinem eigenen Code.
    Es handelt sich um eine ganz gewöhnliche 2 x 16 Bit Wave-Datei.
    Gebe ich ihm eine äquivalente mp3-Datei, funktioniert das in Ansätzen, allerdings mit geänderten Start-Dauer-Werten:
    offset2 /= 8; length2 /= 8;
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Kannst du mir die Datei mal zukommen lassen? Ich hatte auch schon gewöhnliche Dateien, die dann doch ein wenig anders waren, ich hatte for Jahren mal so ein Problem mit in AudaCity erstellten WAVs, die musste ich einmal durch FFMPEG schicken, damit ich die mit der Bass abspielen konnte, das Problem mit in AudaCity erstellten WAVs scheint mittlerweile behoben.(Lag wohl an Audacity)

    Zur Not kannste die Bytes auch selbst aus der Datei hohlen, Wave ist ja einfach gehalten, einen Push-Stream erzeugen mit BASS_StreamCreatePush, diesen fütterst du dann mit BASS_StreamPutData
    bass.radio42.com/help/html/ded…f07-fa20-1aa8335fd31b.htm

    edit @RodFromGermany
    Hab im Forum von Un4seen was gefunden, das war auch bei mir das Problem, könnte das bei dir auch sein?
    un4seen.com/forum/?topic=18939.0

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Takafusa“ ()

    @Takafusa Das wird ja immer schlimmer.
    Nach ffmpeg(MP3 => WAV) kann ich das Wave nicht mehr lesen, er erkennt nur ~50 Samples.
    Als hätte sich das klassische Wave-Format drastisch geändert.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Takafusa schrieb:

    Spielt die bass ohne Probleme.
    Ja, so lange kein Ausschnitt gespielt werden soll. ;(
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ups, da hätte ich besser testen sollen. Das ist ja abenteuerlich. Ich denke einen Bug-Report wert.


    Workaround:

    C#-Quellcode

    1. private SYNCPROC positionSnycProc;
    2. private int stream;
    3. private void Form1_Load(object sender, EventArgs e)
    4. {
    5. Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_CPSPEAKERS, IntPtr.Zero);
    6. stream = Bass.BASS_StreamCreateFile("path", 0, 0, 0);
    7. if (stream != 0)
    8. {
    9. Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, 10.0), BASSMode.BASS_POS_BYTE);
    10. positionSnycProc = new SYNCPROC(PosistionReached);
    11. Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_POS, Bass.BASS_ChannelSeconds2Bytes(stream, 12.0), positionSnycProc, IntPtr.Zero);
    12. Bass.BASS_ChannelPlay(stream, false);
    13. }
    14. else
    15. MessageBox.Show(Bass.BASS_ErrorGetCode().ToString());
    16. }
    17. private void PosistionReached(int handle, int channel, int data, IntPtr user)
    18. {
    19. Bass.BASS_ChannelStop(stream);
    20. }
    Ich hab da noch nen Wave-Analysator gefunden, die ffmpeg-konvertierte Wave kann er lesen, meine nicht.
    Da ist irgend ein Format-Wurm drinne.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Ian hat geantwortet, auch erklärt was Sache ist.(link vorheriger post)

    Seine Empfehlung funktioniert einwandfrei, aber BASSMode.BASS_POS_END ist nicht in der bassNet definiert, nimmste 0x10, hab in der bass.h geschaut.

    C#-Quellcode

    1. stream = Bass.BASS_StreamCreateFile(path, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT);
    2. Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, 10.0F), BASSMode.BASS_POS_BYTE);
    3. Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, 12.0F), (BASSMode)0x10);
    4. Bass.BASS_ChannelPlay(stream, false);

    Danke, @Takafusa, nun kann das neue Jahr beginnen. :thumbsup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!