亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何讓程序在音頻播放完畢后自動退出

如何讓程序在音頻播放完畢后自動退出

Go
慕容森 2022-07-18 17:16:18
我正在寫一個小工具,它可以播放command/terminalsox之類的音頻文件。我正在為 Windows 使用bass.dllGolang syscall。這是我的代碼,文件可以從評論中下載,只能在 Windows X64 上運行。package mainimport (    "fmt"    "syscall"    "time"    "unsafe")/*基于 [bass.dll](http://us2.un4seen.com/files/bass24.zip)和 [Golang syscall](https://github.com/golang/go/wiki/WindowsDLLs) 實現的命令行版播放器。*/type BassLib struct {    libBass syscall.Handle    init   uintptr    free   uintptr    streamCreateFile uintptr    channelPlay uintptr    channelPause uintptr    channelStop uintptr}func (bass *BassLib) LoadBass(bassDllPath string) bool {    bass.libBass, _ = syscall.LoadLibrary(bassDllPath)    if bass.libBass == 0 {        fmt.Println("load library result")        fmt.Println(bass.libBass)        return false    }    bass.init, _ = syscall.GetProcAddress(bass.libBass, "BASS_Init")    // BASS_init(device, freq, flags, win, clsid)    // see http://www.un4seen.com/doc/#bass/BASS_Init.html    device := 1    syscall.Syscall6(bass.init, 5, uintptr(device), uintptr(44100), uintptr(0), uintptr(0), uintptr(0), 0)    return true}func StrPtr(s string) uintptr {    // return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))    p, _ := syscall.UTF16PtrFromString(s)    return uintptr(unsafe.Pointer(p))}有一個大問題:如果未添加time.Sleep代碼(bass.go第 68 行),則不會播放任何聲音并快速退出。當我添加time.Sleep(time.Second * 10)代碼時,音頻持續時間可能超過 10 秒。有沒有可能讓程序在播放完音頻后自動退出?
查看完整描述

3 回答

?
holdtom

TA貢獻1805條經驗 獲得超10個贊

我認為您可以defer在播放功能完成后使用 golang 的關鍵字來觸發退出。


你可以參考這里:圍棋之旅 | 推遲 或在這里:Golang 博客 | 推遲


package main


import "fmt"


func main() {

    defer fmt.Println("world")


    fmt.Println("hello")

}


==========

$ go run main.go

hello

world


查看完整回答
反對 回復 2022-07-18
?
阿波羅的戰車

TA貢獻1862條經驗 獲得超6個贊

我強烈建議您閱讀 golang.org 網站上的Effective Go(閱讀時間不長,我相信您可以在一天內完成所有想法),特別注意并發部分。


Go 背后的整個想法是使并發和異步編程變得容易,它使用了多種語言結構(通道、goroutines),這些結構是專門為幫助您處理這些情況而設計的。


例如,您可以使用通道發出信號:


func main() {    

    

    // end signal

    finished := make(chan bool)

    

    // create and run a goroutine

    go func() {

       // do your bass stuff here

       ...

       

       // send a signal

       finished <- true           

    }()

    

    // wait

    <-finished

}

一種常見的模式是將通道傳遞給執行該工作的函數:


func main() {    

    

    // end signal

    finished := make(chan bool)

    

    // PlayFile is responsible for

    // signalling 'finished' when done

    go PlayFile(someFile, finished);

    

    // wait

    <-finished

}

或者,如果您有多個例程,您將使用WaitGroup:


func main() {


    // create the waitgroup

    var wg sync.WaitGroup


    // number of semaphores

    wg.Add(1)


    go func() {

       // notify WaitGroup when done

       // (the 'defer' keyword means

       // this call will be executed before

       // returning from the method)

       defer wg.Done()

       

       // do your bass stuff here

       ...

    }()


    wg.Wait()

}


查看完整回答
反對 回復 2022-07-18
?
當年話下

TA貢獻1890條經驗 獲得超9個贊

BASS_ChannelGetLength可以用和BASS_ChannelGetPosition功能解決問題。


這是代碼:


// +build windows


package main


import (

    "fmt"

    "syscall"

    "time"

    "unsafe"

)


/*

基于 [bass.dll](http://us2.un4seen.com/files/bass24.zip)

和 [Golang syscall](https://github.com/golang/go/wiki/WindowsDLLs)

實現的命令行版播放器。

*/


type (

    BASSErrorGetCode int32

)


const (

    BassUnicode uint32 = 0x80000000 // BASS_UNICODE

    BassSampleFloat uint32 = 256 // BASS_SAMPLE_FLOAT

    BassPosByte uint64 = 0  // BASS_POS_BYTE

)


type BassLib struct {

    libBass syscall.Handle

    init   uintptr

    free   uintptr

    streamCreateFile uintptr

    channelPlay uintptr

    channelPause uintptr

    channelStop uintptr

    channelGetLength uintptr

    channelGetPosition uintptr

    channelBytes2Seconds uintptr

}


func (bass *BassLib) LoadBass(bassDllPath string) bool {

    bass.libBass, _ = syscall.LoadLibrary(bassDllPath)

    if bass.libBass == 0 {

        fmt.Println("Load `bass.dll` library failed!")

        errCode := bass.GetBassErrorGetCode()

        fmt.Println("Bass_Init failed!")

        fmt.Println(errCode)

        return false

    }

    bass.init, _ = syscall.GetProcAddress(bass.libBass, "BASS_Init")

    // BASS_Init(device, freq, flags, win, clsid)

    // see http://www.un4seen.com/doc/#bass/BASS_Init.html

    device := 1

    r, _, _ := syscall.Syscall6(bass.init, 5, uintptr(device), uintptr(44100), uintptr(0), uintptr(0), uintptr(0), 0)

    // var ret = *(* int)(unsafe.Pointer(&r))

    if r == 0 {

        errCode := bass.GetBassErrorGetCode()

        fmt.Println("Bass_Init failed!")

        fmt.Println(errCode)

        return false

    }

    return true

}



func StrPtr(s string) uintptr {

    p, _ := syscall.UTF16PtrFromString(s)

    return uintptr(unsafe.Pointer(p))

}


func (bass *BassLib) PlayFile(filePath string) {

    bass.streamCreateFile, _ = syscall.GetProcAddress(bass.libBass, "BASS_StreamCreateFile")

    // hStream = BASS_StreamCreateFile(mem=0, &file, offset=0, length=0, flags=(A_IsUnicode ? 0x80000000 : 0x40000))

    // see http://www.un4seen.com/doc/#bass/BASS_StreamCreateFile.html

    hStream, _, _ := syscall.Syscall6(bass.streamCreateFile, 5,  uintptr(0), StrPtr(filePath), uintptr(0), uintptr(0), uintptr(BassUnicode|BassSampleFloat), 0)

    bass.channelPlay, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPlay")

    // BASS_ChannelPlay(hStream)

    // see http://www.un4seen.com/doc/#bass/BASS_ChannelPlay.html

    r, _, _ := syscall.Syscall(bass.channelPlay, 2, hStream, uintptr(0), 0)

    if r == 1 {

        totalDuration := bass.GetAudioByteLength(hStream)

        // currentPos := bass.GetAudioCurrentBytePosition(hStream)

        fmt.Println(totalDuration)

        // fmt.Println(currentPos)

        time.Sleep(time.Second*1)

        for {

            currentPos := bass.GetAudioCurrentBytePosition(hStream)

            if currentPos >= totalDuration {

                break

            }

        }

    } else {

        errCode := bass.GetBassErrorGetCode()

        fmt.Println("Bass_ChannelPlay failed!")

        fmt.Println(errCode)

    }

}


func (bass *BassLib) GetBassErrorGetCode() BASSErrorGetCode {

    bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")

    // BASS_ErrorGetCode()

    // BASS_OK              BASSErrorGetCode = 0    // all is OK

    // BASS_ERROR_MEM       BASSErrorGetCode = 1    // memory error

    // ...

    // see http://www.un4seen.com/doc/#bass/BASS_ErrorGetCode.html

    errCode, _, _ := syscall.Syscall(bassErrorGetCode, 0, 0, 0, 0)

    var iErrCode = *(*BASSErrorGetCode)(unsafe.Pointer(&errCode))

    return iErrCode

}


func (bass *BassLib) GetAudioByteLength(handle uintptr) uintptr {

    // (QWORD) BASS_ChannelGetLength(handle=hStream, mode)

    // see http://www.un4seen.com/doc/#bass/BASS_ChannelGetLength.html

    bass.channelGetLength, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetLength")

    len, _, _ := syscall.Syscall(bass.channelGetLength, 2, handle,  uintptr(BassPosByte), 0)

    return len

}



func (bass *BassLib) GetAudioCurrentBytePosition(handle uintptr) uintptr {

    // BASS_ChannelGetPosition(handle=hStream, mode)

    // see http://www.un4seen.com/doc/#bass/BASS_ChannelGetPosition.html

    bass.channelGetPosition, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetPosition")

    pos, _, _ := syscall.Syscall(bass.channelGetPosition, 2, handle,  uintptr(BassPosByte), 0)

    return pos

}


func (bass *BassLib) GetChannelBytes2Seconds(handle uintptr, pos uintptr) uintptr {

    // BASS_ChannelBytes2Seconds(handle=hStream, pos)

    // see http://www.un4seen.com/doc/#bass/BASS_ChannelBytes2Seconds.html

    // bass.channelBytes2Seconds, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelBytes2Seconds")

    len, _, _ := syscall.Syscall(bass.channelBytes2Seconds, 2, handle, pos, 0)

    return len

}





func (bass *BassLib) UnLoad() {

    if bass.libBass != 0 {

        bass.free, _ = syscall.GetProcAddress(bass.libBass, "BASS_Free")

        syscall.Syscall(bass.free, 0, 0, 0, 0)

        // BASS_Free()

        // see http://www.un4seen.com/doc/#bass/BASS_Free.html

        syscall.FreeLibrary(bass.libBass)

    }

}


func main() {

    bass := &BassLib{}

    bass.LoadBass("C:\\workspace\\play\\bass.dll")

    bass.PlayFile("C:\\workspace\\play\\sample.mp3")

    bass.UnLoad()

}

您也可以訪問https://gist.github.com/ycrao/e7d1df181f870091b4a6d298d6ea2770#file-bass_play-go-L81-L91。


查看完整回答
反對 回復 2022-07-18
  • 3 回答
  • 0 關注
  • 206 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號