Mit Bass.net die Tonhöhe anpassen - kein Ton bei BASS_STREAM_DECODE-Flag

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von Dralnaw.

    Mit Bass.net die Tonhöhe anpassen - kein Ton bei BASS_STREAM_DECODE-Flag

    Hallo,

    ich versuche, mit bass.net Musik vom Line-In Eingang des Computers über die Lautsprecher abzuspielen, und dabei den Pitch (Tonhöhe) der Musik zu verändern.
    Problem dabei ist, dass zum Ändern der Tonhöhe das BASS_STREAM_DECODE-Flag gesetzt sein muss, wodurch ich offenbar den Stream nicht mehr abspielen kann (zumindest bleiben die Lautsprecher stumm).

    Mein aktueller Testcode:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports Un4seen.Bass
    2. Imports Un4seen.Bass.AddOn.Fx.BassFx
    3. Imports Un4seen.Bass.Bass
    4. Public Class Form1
    5. Const INDEV As Integer = 2 'Line In
    6. Const OUTDEV As Integer = 1 'Lautsprecher
    7. Dim hndInStream As Integer
    8. Dim hndOutStream As Integer
    9. Dim rp As New RECORDPROC(AddressOf recProc)
    10. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    11. printDevices()
    12. err(BASS_Init(OUTDEV, 44100, 0, Me.Handle), "BASS_Init")
    13. hndOutStream = err(BASS_StreamCreate(44100, 2, BASSFlag.BASS_STREAM_DECODE, BASSStreamProc.STREAMPROC_PUSH), "BASS_StreamCreate")
    14. hndOutStream = err(BASS_FX_TempoCreate(hndOutStream, 0), "BASS_FX_TempoCreate")
    15. err(BASS_ChannelSetAttribute(hndOutStream, BASSAttribute.BASS_ATTRIB_TEMPO_PITCH, 6), "BASS_ChannelSetAttribute")
    16. err(BASS_RecordInit(INDEV), "BASS_RecordInit")
    17. hndInStream = err(BASS_RecordStart(44100, 2, 0, 10, rp, IntPtr.Zero), "BASS_RecordStart")
    18. err(BASS_ChannelPlay(hndOutStream, False), "BASS_ChannelPlay")
    19. End Sub
    20. Function recProc(handle As Integer, buffer As System.IntPtr, length As Integer, user As System.IntPtr) As Boolean
    21. BASS_StreamPutData(hndOutStream, buffer, length)
    22. Return True
    23. End Function
    24. ...
    (Die Funktion err() dient lediglich dazu, im Fehlerfall eine Meldung anzuzeigen.)


    Lasse ich die Anweisungen BASS_FX_TempoCreate sowie BASS_ChannelSetAttribute weg und entferne ich das Flag BASSFlag.BASS_STREAM_DECODE, kann ich problemlos die Musik des Line-In-Eingangs auf den Lautsprechern hören - nur kann ich dann logischerweise die Tonhöhe nicht anpassen.

    Woran liegt das, bzw. wie muss ich vorgehen, damit ich dennoch die Tonhöhe anpassen kann?
    Ach so... ich dachte, du meintest, dass das Problem bei den verwendenten Flags liegt.
    Wenn ich mir die möglichen Flags aber nochmal anschaue, sieht es für mich nicht wirklich danach aus, dass es daran liegen könnte :(
    Spoiler anzeigen

    BASS_SAMPLE_8BITS
    Use 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the stream is 16-bit.
    BASS_SAMPLE_FLOAT
    Use 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info.
    BASS_SAMPLE_SOFTWARE
    Force the stream to not use hardware mixing.
    BASS_SAMPLE_3D
    Use 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling BASS_Init(Int32, Int32, BASSInit, IntPtr, IntPtr). 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag.
    BASS_SAMPLE_FX
    Requires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use BASS_ChannelSetFX(Int32, BASSFXType, Int32) to add effects to the stream.
    BASS_STREAM_AUTOFREE
    Automatically free the stream's resources when it has reached the end, or when BASS_ChannelStop(Int32) (or BASS_Stop) is called.
    BASS_STREAM_DECODE
    Decode the sample data, without outputting it. Use BASS_ChannelGetData(Int32, IntPtr, Int32)
    to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE,
    BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags
    can not be used together with this flag.
    BASS_SPEAKER_xxx
    Speaker assignment flags.


    Ich habe es auch schon mal mit einem Dummy-Stream (STREAMPROC_DUMMY) versucht, aber das hat auch nicht funktioniert (selbes Verhalten, wie eingangs beschrieben - lediglich ein "knacken" gabs ab und zu).
    OK, mit dem BASS_FX_BFX_PITCHSHIFT-Effekt sollte es funktionieren. Eigenartigerweise bekomme ich bei BASS_FXSetParameters den Fehler BASS_ERROR_ILLPARAM, obwohl ich params testweise mal nur mit den Default-Werten gefüllt habe.
    Habe ich irgendeinen trivialen Fehler gemacht, den ich jetzt nicht finde? Normalerweise sollten die Standartwerte doch unprobelmatisch sein, oder?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. printDevices()
    3. err(BASS_Init(OUTDEV, 44100, 0, Me.Handle), "BASS_Init")
    4. err(Un4seen.Bass.AddOn.Fx.BassFx.LoadMe(), "LoadMe")
    5. hndOutStream = err(BASS_StreamCreate(44100, 2, BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_SAMPLE_FLOAT, BASSStreamProc.STREAMPROC_PUSH), "BASS_StreamCreate")
    6. hndFX = err(Bass.BASS_ChannelSetFX(hndOutStream, BASSFXType.BASS_FX_BFX_PITCHSHIFT, 0), "BASS_ChannelSetFX")
    7. Dim params As New BASS_BFX_PITCHSHIFT() With {
    8. .fPitchShift = 1S,
    9. .fSemitones = 0S,
    10. .lChannel = BASSFXChan.BASS_BFX_CHANALL,
    11. .lFFTsize = 2048,
    12. .lOsamp = 8L
    13. }
    14. err(BASS_FXSetParameters(hndFX, params), "BASS_FXSetParameters")
    15. err(BASS_RecordInit(INDEV), "BASS_RecordInit")
    16. hndInStream = err(BASS_RecordStart(44100, 2, 0, 10, rp, IntPtr.Zero), "BASS_RecordStart")
    17. err(BASS_ChannelPlay(hndOutStream, False), "BASS_ChannelPlay")
    18. End Sub
    Hab das auch mal getestet mit BASS_BFX_PITCHSHIFT, aus unerklärlichen Gründen blieb das ohne Effekt ?( .
    Allerdings funktioniert das so ganz gut.

    VB.NET-Quellcode

    1. Imports Un4seen.Bass
    2. Imports Un4seen.Bass.AddOn.Fx
    3. Public Class Form1
    4. Private a_stream, b_stream As Integer
    5. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_CPSPEAKERS, IntPtr.Zero, Nothing)
    7. Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PREBUF, 750)
    8. Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PLAYLIST, 1)
    9. Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_BUFFER, 750)
    10. Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 50)
    11. BassFx.LoadMe()
    12. a_stream = Bass.BASS_StreamCreateURL("http://stream.raggakings.net:8000", 0, BASSFlag.BASS_STREAM_DECODE, Nothing, IntPtr.Zero)
    13. b_stream = BassFx.BASS_FX_TempoCreate(a_stream, BASSFlag.BASS_FX_FREESOURCE)
    14. Bass.BASS_ChannelPlay(b_stream, False)
    15. End Sub
    16. Private Sub TrackBar1_Scroll(sender As Object, e As EventArgs) Handles TrackBar1.Scroll
    17. Bass.BASS_ChannelSetAttribute(b_stream, BASSAttribute.BASS_ATTRIB_TEMPO_PITCH, TrackBar1.Value)
    18. End Sub
    19. End Class

    Ja, so funktioniert das wirklich ganz gut... nur leider kann ich den Stream nicht abspielen, wenn ich ihn über BASS_StreamCreate erstelle - der Fehler BASS_ERROR_DECODE tritt auf (bzw. wenn ich vorher BASS_FX_TempoCreate aufrufe, gibt's einfach kein Ausgangssignal).

    Aber mir ist vorhin etwas in der Bass-Dokumentation aufgefallen (aus dem Objektkatalog):
    Public Const STREAMPROC_DUMMY As Un4seen.Bass.BASSStreamProc = 0
    Member von Un4seen.Bass.BASSStreamProc
    Zusammenfassung:
    Create a "dummy" stream.
    A dummy stream doesn't have any sample data of its own, but a decoding dummy stream (with BASS_STREAM_DECODE flag) can be used to apply DSP/FX processing to any sample data, by setting DSP/FX on the stream and feeding the data through Un4seen.Bass.Bass.BASS_ChannelGetData(System.Int32,System.IntPtr,System.Int32). The dummy stream should have the same sample format as the data being fed through it.

    Das heißt also, dass ich die Daten aus meinem Line-In-Stream erst in den Dummy-Stream schicken sollte, dort den Pitchshift-Effekt anwenden kann und anschließend in einem Ausgabe-Stream (Push-Stream?) die verarbeiteten Daten abspielen kann, oder?

    Anscheinend kann ich bei einem Push-Stream nicht direkt bestimmte Effekte festlegen - bei einem Stream, der über BASS_StreamCreateURL oder BASS_StreamCreateFile erzeugt wurde, offenbar schon.



    Edit:
    ...und da kommt schon das nächste Problem: ich habe bisher keine Möglichkeit gefunden, Samples in einen DummyStream zu schreiben - geht das überhaupt? Wie soll ein DummyStream verwendet werden?
    Offenbar muss ich irgendwie einen Decode-Stream erzeugen, in den ich Samples schreiben und diese auslesen kann - geht das denn? Ist das überhaupt der richtige Ansatz?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Dralnaw“ ()

    So, ich habe die Lösung zur ursprünglichen Problemstellung ("es wird nichts abgespielt") in einem anderen Forum erhalten.
    Bei dem Record-Callback (recProc)

    Dralnaw schrieb:

    VB.NET-Quellcode

    1. BASS_StreamPutData(hndOutStream, buffer, length)
    mache ich den Fehler, den falschen Stream zu verwenden.

    Es muss eigentlich

    VB.NET-Quellcode

    1. BASS_StreamPutData(BASS_FX_TempoGetSource(hndOutStream), buffer, length)
    heißen.
    Denn die Daten sollen logischerweise nicht in den TempoStream, sondern in den PushStream geschrieben werden.

    Dennoch danke für die Hilfe hier :)