• wxpython多线程通信的应用-实现边录音边绘制音谱图


    #!bin/bash/python
    # -*- coding=utf-8 -*-
    from __future__ import division
    
    import threading
    import wx
    import wx.media
    import os.path, os, gc, sys, pyaudio
    import wave, numpy, codecs, time
    import pylab as pl
    import pyaudio
    #import win32gui
    from matplotlib.ticker import MultipleLocator, FormatStrFormatter
    import sys
    from wx.lib.pubsub import pub
    
    
    reload(sys)
    
    wavCount = 1
    input_filename = "input.wav"               # 麦克风采集的语音输入
    input_filepath = "./"                      # 输入文件的path
    in_path = input_filepath + input_filename
    global_frames = []
    xmajorLocator   = MultipleLocator(0.5)        # 将x主刻度标签设置为0.5的倍数
    xmajorFormatter = FormatStrFormatter('%1.1f') # 设置x轴标签文本的格式
    xminorLocator   = MultipleLocator(0.05)       # 将x轴次刻度标签设置为0.05的倍数
    
    class MyFrame(wx.Frame):
        #初始化全部界面
        def __init__(self, wavlist, recList):
            self.wavTime = 0.000
            self.wavLength = 0.000
            self.labelcount = 0
            self.choosenItem = 0
            self.labelPosition = 0
            self.cutCount = 1
            self.wavList = []
            self.recList = []
            self.labellist = []
            self.labelPos = []
            self.tempwavlist = []
            self.wavList = wavlist
            self.recList = recList
            # self.wavfilepath = wavlist[0][1]
            # self.recTextStr = recList[0][1]
            self.wavfilepath = wavlist[0]
            self.recTextStr = recList[0]
            print ("wav:", self.wavfilepath)
            print ("rec:", self.recTextStr)
            wx.Frame.__init__(self,None,size=(1920,1080))
    
            self.sp=wx.SplitterWindow(self,style=wx.SP_3D)
            self.mainPanel=wx.Panel(self.sp)
            self.listPanel=wx.Panel(self.sp)
            self.sp2=wx.SplitterWindow(self.mainPanel)
            self.annoPanel=wx.Panel(self.sp2)
            self.subPanel=wx.Panel(self.sp2)
            self.box=wx.BoxSizer(wx.VERTICAL)
            self.box.Add(self.sp2,1,wx.EXPAND)
            self.sp3=wx.SplitterWindow(self.subPanel)
            self.cutPanel=wx.Panel(self.sp3)
            self.statisticPanel=wx.Panel(self.sp3)
            self.box2=wx.BoxSizer(wx.VERTICAL)
            self.box2.Add(self.sp3,1,wx.EXPAND)
            self.sp4=wx.SplitterWindow(self.statisticPanel)
            self.wavPanel=wx.Panel(self.sp4)
            # upgrade
            # self.upwavPanel=wx.Panel(self.sp4)
            self.infoPanel=wx.Panel(self.sp4)
            self.box3=wx.BoxSizer(wx.VERTICAL)
            self.box3.Add(self.sp4,1,wx.EXPAND)
            self.sp5=wx.SplitterWindow(self.infoPanel)
            self.labelPanel=wx.Panel(self.sp5)
            self.aaaPanel=wx.Panel(self.sp5)
            self.box4=wx.BoxSizer(wx.VERTICAL)
            self.box4.Add(self.sp5,1,wx.EXPAND)
            self.sp6=wx.SplitterWindow(self.aaaPanel)
            self.bbbPanel=wx.Panel(self.sp6)
            self.cccPanel=wx.Panel(self.sp6)
            self.box5=wx.BoxSizer(wx.VERTICAL)
            self.box5.Add(self.sp6,1,wx.EXPAND)
            self.mainPanel.SetSizer(self.box)
            self.subPanel.SetSizer(self.box2)
            self.statisticPanel.SetSizer(self.box3)
            self.infoPanel.SetSizer(self.box4)
            self.aaaPanel.SetSizer(self.box5)
            self.cutPanel.SetBackgroundColour("white")
            self.bbbPanel.SetBackgroundColour("white")
            self.cccPanel.SetBackgroundColour("white")
            print ("debug: wavfilepath:", self.wavfilepath)
            self.drawBackJpg(str(self.wavfilepath))
    
            # 创建布局
            self.CreateListUI(wavlist)
            self.CreateMainUI(recList)
            self.CreateWavUI()
            self.CreateLabelListUI()
    
            # 布局
            self.sp.SplitVertically(self.listPanel,self.mainPanel,150)
            self.sp2.SplitHorizontally(self.annoPanel,self.subPanel,300)
            self.sp3.SplitHorizontally(self.cutPanel,self.statisticPanel,110)
            self.sp4.SplitHorizontally(self.wavPanel,self.infoPanel,280)
            self.sp5.SplitHorizontally(self.labelPanel,self.aaaPanel,100)
            self.sp6.SplitVertically(self.bbbPanel,self.cccPanel,820)
            self.Bind(wx.EVT_LIST_ITEM_SELECTED,self.OnListBox,self.list)
            self.wavPanel.Bind(wx.EVT_PAINT, self.OnPaint)
            self.wavPanel.Bind(wx.EVT_ERASE_BACKGROUND,self.OnErasePass)
            self.wavPanel.Bind(wx.EVT_MOTION,self.OnMove)
            self.wavPanel.Bind(wx.EVT_LEFT_DOWN,self.OnLeftDown)
            self.wavPanel.Bind(wx.EVT_LEFT_UP,self.OnDrawRec)
            # self.upwavPanel.Bind(wx.EVT_PAINT, self.OnPaint)
            # self.upwavPanel.Bind(wx.EVT_ERASE_BACKGROUND,self.OnErasePass)
            # self.upwavPanel.Bind(wx.EVT_MOTION,self.OnMove)
            # self.upwavPanel.Bind(wx.EVT_LEFT_DOWN,self.OnLeftDown)
            # self.upwavPanel.Bind(wx.EVT_LEFT_UP,self.OnDrawRec)
            self.labelPanel.Bind(wx.EVT_MOTION,self.OnLabelMove)
            self.labelPanel.Bind(wx.EVT_LEFT_UP,self.OnLabelDrawLine)
            self.labelPanel.Bind(wx.EVT_PAINT,self.OnLabelPaint)
            self.labelPanel.Bind(wx.EVT_ERASE_BACKGROUND,self.OnErasePass)
    
        #左侧列表的点击事件
        def OnListBox(self,event):
            # self.sp.Unsplit()
            if self.timer:
                self.timer.Stop()
                # del self.timer
            self.cutCount=1
    
            #获取点击对象
            index = event.GetIndex()
            self.choosenItem = index
            data = self.list.GetItem(index,0)
            tuple_temp = self.wavList[int(data.GetText())-1]
            # self.wavfilepath = tuple_temp[1]
            # self.recTextStr = self.recList[int(data.GetText())-1][1]
            self.wavfilepath = self.wavfilepath
            self.recTextStr = self.recTextStr
            print ("wav:", self.wavfilepath)
            print ("rec:", self.recTextStr)
            self.OnFreshUI()
            #刷新界面
    
    
        def OnFreshUI(self):
            self.InitMedia()
            self.rec_tc.SetValue(self.recTextStr)
            self.label_tc.SetValue("")
            self.anno_tc.SetValue("")
            self.wavpath_ST.SetLabel(u"当前操作文件 : "+ self.wavfilepath)
    
            self.drawBackJpg(str(self.wavfilepath))
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.OnTimer)
            self.timer.Start(100)
            self.cutPanel.Refresh()
            self.annoPanel.Refresh()
            self.mainPanel.Refresh()
    
        #绘制音频波形的paint事件的回调函数
        def OnPaint(self, event):
            brush = wx.Brush("white")
            img = wx.Bitmap("mic4_output.png")
            dc = wx.BufferedPaintDC(self.wavPanel)
            dc.SetBackground(brush)
            # dc.Clear()
            dc.DrawBitmap(img,-172,0)
    
        #据说可以解决屏闪问题
        def OnErasePass(self, event):
            pass
    
        #--------------------------------------------------
        #列表界面的UI创建
        def CreateListUI(self,wavlist):
            self.ListBox = wx.BoxSizer(wx.HORIZONTAL)
            self.list = wx.ListCtrl(self.listPanel, -1, style=wx.LC_REPORT)
            self.list.InsertColumn(0, u'序号', width=50)
            self.list.InsertColumn(1, u'完成情况', width=150)
            for i in wavlist:
                index = self.list.InsertStringItem(sys.maxint, str(i[0]))
                self.list.SetStringItem(index, 1, u"未完成")
            self.ListBox.Add(self.list,1,wx.EXPAND)
            self.listPanel.SetSizerAndFit(self.ListBox)
        #--------------------------------------------------
        #标注界面的UI创建
    
        #wx.media的load初始化
        def InitMedia(self):
            try:
                self.mc = wx.media.MediaCtrl(self.mainPanel, style=wx.SIMPLE_BORDER)
            except NotImplementedError:
                self.Destroy()
                raise
    
            if not self.mc.Load(self.wavfilepath):
                wx.MessageBox("Unable to load: Unsupported format?","ERROR", wx.ICON_ERROR | wx.OK)
            else:
                print "load success"
                print self.mc.Length()
                self.slider.SetRange(0, self.mc.Length())
            #self.mc.Pause=0
    
        #初始完成后各按键才可使用
        def OnMediaLoaded(self, evt):
            self.buttonPlay.Enable()
    
        #创建标注界面(播放器,文本框)
        def CreateMainUI(self,recList):
            font=wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
            font.SetPointSize(12)
            font20=wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
            font20.SetPointSize(16)
            self.annoPanel.SetBackgroundColour("white")
            self.MainSizer=wx.GridBagSizer(0,0)
            self.num_st=wx.StaticText(self.annoPanel,label="")
            self.num_st.SetFont(font)
            self.MainSizer.Add(self.num_st,pos=(0,0),span=(1,2),flag=wx.ALL,border=10)
            self.num1=wx.StaticText(self.annoPanel,label="",style=wx.ALIGN_CENTER)
            self.num1.SetFont(font)
            self.MainSizer.Add(self.num1,pos=(2,0),span=(1,2),flag=wx.ALL,border=10)
            self.wav_st=wx.StaticText(self.annoPanel,label=u"音频")
            self.wav_st.SetFont(font)
            self.MainSizer.Add(self.wav_st,pos=(0,2),span=(1,5),flag=wx.EXPAND|wx.ALL,border=10)
            self.MainSizer.AddGrowableCol(6,1)
            self.buttonPlay=wx.Button(self.annoPanel,wx.ALL,label=u"&▷	F1")
            self.buttonPause=wx.Button(self.annoPanel,label=u"&‖	Esc")
            self.buttonStop=wx.Button(self.annoPanel,label=u"&■	Ctrl-S")
            self.Bind(wx.EVT_BUTTON,self.playWav,self.buttonPlay)
            #accelTb1 = wx.AcceleratorTable([wx.ACCEL_CTRL,ord('S'),self.buttonPlay.GetId()])
            #self.SetAcceleratorTable(accelTb1)
            self.Bind(wx.EVT_BUTTON,self.pauseWav,self.buttonPause)
            self.Bind(wx.EVT_BUTTON,self.stopWav,self.buttonStop)
            self.MainSizer.Add(self.buttonPlay,pos=(2,2),flag=wx.ALL,border=10)
            self.MainSizer.Add(self.buttonPause,pos=(2,3),flag=wx.ALL,border=10)
            self.MainSizer.Add(self.buttonStop,pos=(2,4),flag=wx.ALL,border=10)
            self.slider=wx.Slider(self.annoPanel,-1,0,0,1)
            self.slider.SetMinSize((150,-1))
            self.MainSizer.Add(self.slider,pos=(3,2),span=(1,3),flag=wx.ALL|wx.EXPAND,border=10)
            self.Bind(wx.EVT_SLIDER,self.OnSeek,self.slider)
            self.timer=wx.Timer(self)
            self.Bind(wx.EVT_TIMER,self.OnTimer)
            self.timer.Start(100)
            self.rec_st=wx.StaticText(self.annoPanel,label=u"语音识别结果")
            self.rec_st.SetFont(font)
            self.MainSizer.Add(self.rec_st,pos=(0,7),span=(1,4),flag=wx.EXPAND|wx.ALL,border=10)
            self.MainSizer.AddGrowableCol(10,1)
            self.rec_tc=wx.TextCtrl(self.annoPanel,value=self.recTextStr,style=wx.TE_READONLY|wx.TE_MULTILINE)
            self.MainSizer.Add(self.rec_tc,pos=(2,7),span=(4,4),flag=wx.EXPAND|wx.ALL,border=10)
            self.label_st=wx.StaticText(self.annoPanel,label=u"音频标记")
            self.label_st.SetFont(font)
            self.MainSizer.Add(self.label_st,pos=(0,12),flag=wx.ALL,border=10)
            self.label_tc=wx.TextCtrl(self.annoPanel,style=wx.TE_MULTILINE)
            self.MainSizer.Add(self.label_tc,pos=(2,12),span=(4,1),flag=wx.EXPAND|wx.ALL,border=10)
            self.anno_st=wx.StaticText(self.annoPanel,label=u"文本标注")
            self.anno_st.SetFont(font)
            self.MainSizer.Add(self.anno_st,pos=(0,13),span=(1,4),flag=wx.EXPAND|wx.ALL,border=10)
            self.MainSizer.AddGrowableCol(16,1)
            self.anno_tc=wx.TextCtrl(self.annoPanel,style=wx.TE_MULTILINE)
            self.MainSizer.Add(self.anno_tc,pos=(2,13),span=(4,4),flag=wx.EXPAND|wx.ALL,border=10)
            self.line=wx.StaticLine(self.annoPanel)
            self.MainSizer.Add(self.line,pos=(1,0),span=(1,18),flag=wx.EXPAND|wx.BOTTOM,border=10)
            self.save_button=wx.Button(self.annoPanel,label=u"保存")
            self.clear_button=wx.Button(self.annoPanel,label=u"清空")
            self.MainSizer.Add(self.save_button,pos=(2,17),flag=wx.ALL,border=10)
            self.MainSizer.Add(self.clear_button,pos=(3,17),flag=wx.ALL,border=10)
            self.save_button.Bind(wx.EVT_BUTTON,self.ButtonSave)
            self.clear_button.Bind(wx.EVT_BUTTON,self.ButtonClear)
            self.InitMedia()
            self.annoPanel.SetSizerAndFit(self.MainSizer)
    
        #播放器进度条的定时器事件回调
        def OnSeek(self, evt):
            offset = self.slider.GetValue()
            self.mc.Seek(offset)
    
        def OnTimer(self, evt):
            offset = self.mc.Tell()
            self.slider.SetValue(offset)
    
        #保存结果
        def ButtonSave(self,event):
            with codecs.open('anno_file','w','gbk') as f:
                anno_text = self.anno_tc.GetValue()
                print anno_text
                f.write(anno_text)
            self.list.SetStringItem(self.choosenItem,1,u"完成")
            self.list.SetItemBackgroundColour(self.choosenItem,"green")
            #删除中间操作的temp文件,并对最后保存的文件重命名
            if len(self.tempwavlist) != 0:
                lastfile=self.tempwavlist[-1]
                self.tempwavlist.pop()
                for i in self.tempwavlist:
                    print i
                    os.remove(i)
                data = self.list.GetItem(self.choosenItem,0)
                tuple_temp = self.wavList[int(data.GetText())-1]
                print tuple_temp
                path_str=os.path.split(tuple_temp[1])
                wavname=path_str[1].split('.')
                newname=wavname[0]+"_nocut."+wavname[1]
                newpath=os.path.join(path_str[0],newname)
                print newpath
                os.rename(tuple_temp[1],newpath)
                os.rename(lastfile,tuple_temp[1])
    
        #清空标注文本框
        def ButtonClear(self,event):
            self.anno_tc.SetValue("")
            self.label_tc.SetValue("")
    
        #播放器播放
        def playWav(self,event):
            if not self.mc.Play():
                wx.MessageBox("Unable to Play media : Unsupported format?","ERROR",wx.ICON_ERROR | wx.OK)
            else:
                print self.mc.Length()
                self.slider.SetRange(0, self.mc.Length())
    
        #播放器暂停
        def pauseWav(self,event):
            #if self.mc.Pause == 0:
            #   pygame.mixer.music.pause()
            #  self.buttonPause.SetLabel(u"▷")
            # self.mc.Pause = 1
            #else:
            #   pygame.mixer.music.unpause()
            #  self.buttonPause.SetLabel(u"‖")
            # self.mc.Pause = 0
            self.mc.Pause()
    
        #播放器停止
        def stopWav(self,event):
            self.mc.Stop()
    
        #--------------------------------------------------
        #标签操作的UI创建
        def OnLabelPaint(self,event):
            brush=wx.Brush("white")
            dc2=wx.PaintDC(self.labelPanel)
            dc2.SetBackground(brush)
            dc2.Clear()
            dc2.DrawRectangle(79,30,1550,40)
            for i in self.labelPos:
                print i
                dc4=wx.PaintDC(self.labelPanel)
                dc4.DrawLine(i,30,i,70)
    
        #--------------------------------------------------
        #音频操作的UI创建
        def CreateWavUI(self):
            self.haveDraw = 0
            self.haveCut = 0
            self.wavpath_ST = wx.StaticText(self.cutPanel,-1,u"当前操作文件 : "+self.wavfilepath,pos=(40,10))
            wx.StaticText(self.cutPanel,-1,u"时间 : ",pos=(40,60))
            wx.StaticText(self.cutPanel,-1,u"坐标:",pos=(600,60))
            self.labelButton=wx.Button(self.cutPanel,-1,"label",pos=(200,60))
            self.cutButton=wx.Button(self.cutPanel,-1,"delete",pos=(300,60))
            self.playButton=wx.Button(self.cutPanel,-1,"play",pos=(400,60))
            self.posCtrl=wx.TextCtrl(self.cutPanel,-1,"",pos=(640,60))
            self.timeCtrl=wx.TextCtrl(self.cutPanel,-1,"",pos=(80,60))
            self.Bind(wx.EVT_BUTTON,self.OnLabelCreate,self.labelButton)
            self.Bind(wx.EVT_BUTTON,self.cutWav,self.cutButton)
            self.Bind(wx.EVT_BUTTON,self.PlayWav,self.playButton)
            self.testbutton=wx.Button(self.cutPanel, -1, "revoke", pos=(500,60))
            self.Bind(wx.EVT_BUTTON,self.testtest, self.testbutton)
    
            # 录音
            self.recordBtn = wx.Button(self.cutPanel, -1, "Record", pos=(750, 61))
            self.Bind(wx.EVT_BUTTON, self.OnPaint2, self.recordBtn)
    
            # 接收消息,
            pub.subscribe(self.record_and_drawBackJpg, "update")
    
        # 待实现--还没写
        def CreateUpWavUI(self):
            self.uphaveDraw = 0
            self.uphaveCut = 0
            self.upwavpath_ST = wx.StaticText(self.upcutPanel,-1,u"当前操作文件 : "+self.wavfilepath,pos=(40,10))
            wx.StaticText(self.upcutPanel, -1, u"时间 : ", pos = (40,60))
            wx.StaticText(self.upcutPanel, -1, u"坐标:", pos = (600,60))
            self.uplabelButton=wx.Button(self.upcutPanel,-1,"label",pos=(200,60))
            self.upcutButton=wx.Button(self.upcutPanel,-1,"delete",pos=(300,60))
            self.upplayButton=wx.Button(self.upcutPanel,-1,"play",pos=(400,60))
            self.upposCtrl=wx.TextCtrl(self.upcutPanel,-1,"",pos=(640,60))
            self.uptimeCtrl=wx.TextCtrl(self.upcutPanel,-1,"",pos=(80,60))
            self.Bind(wx.EVT_BUTTON,self.OnLabelCreate,self.uplabelButton)
            self.Bind(wx.EVT_BUTTON,self.cutWav,self.upcutButton)
            self.Bind(wx.EVT_BUTTON,self.PlayWav,self.upplayButton)
            self.uptestbutton=wx.Button(self.cutPanel,-1,"revoke",pos=(500,60))
            self.Bind(wx.EVT_BUTTON,self.testtest,self.uptestbutton)
            self.upecordBtn = wx.Button(self.cutPanel, -1, "Record", pos=(750, 61))
            self.Bind(wx.EVT_BUTTON, self.OnPaint2, self.uprecordBtn)
    
        #左键按下事件的回调函数,绘制一条线
        def OnLeftDown(self,event):
            self.wavPanel.Refresh()
            self.firstPos=event.GetPosition()
            #haveDraw为判断是否左键按下后是否有拖动动作
            if self.haveDraw == 1:
                self.haveDraw = 0
                dc=wx.BufferedDC(wx.ClientDC(self.wavPanel))#,self.wavPanel
                # dc=wx.BufferedPaintDC(self.wavPanel)
                dc.DrawLine(self.firstPos.x, 30, self.firstPos.x, 270)
    
        #左键松开事件的回调函数,绘制选中的矩形框
        def OnDrawRec(self,event):
            #haveDraw为判断是否左键按下后是否有拖动拖动动作
            if self.haveDraw == 1:
                dc=wx.BufferedDC(wx.ClientDC(self.wavPanel))
                #dc=wx.BufferedPaintDC(self.wavPanel)
                brush=wx.Brush(wx.Colour(255,23,140))
                dc.SetBrush(brush)
                dc.SetBrush(wx.Brush(wx.Colour(255,23,140),wx.BDIAGONAL_HATCH))
                dc.DrawRectangle(self.firstPos.x,30,self.secondPos.x-self.firstPos.x,240)
            else:
                #dc=wx.PaintDC(self.wavPanel)
                dc=wx.BufferedDC(wx.ClientDC(self.wavPanel))#,self.wavPanel
                dc.DrawLine(self.firstPos.x,30,self.firstPos.x,270)
    
        def OnMove(self, event):
            pos=event.GetPosition()
            self.posCtrl.SetValue("%s,%s" %(pos.x,pos.y))
            #在左键按下和拖动下绘制选中的矩形框
            if event.Dragging() and event.LeftIsDown():
                self.secondPos=pos
                self.wavPanel.Refresh()
                dc = wx.BufferedDC(wx.ClientDC(self.wavPanel))
                #dc=wx.BufferedPaintDC(self.wavPanel)
                brush=wx.Brush(wx.Colour(100,100,100))
                dc.SetBrush(brush)
                dc.SetBrush(wx.Brush(wx.Colour(255,23,140),wx.BDIAGONAL_HATCH))
                if self.firstPos.x<80 :
                    self.firstPos = 250
                if self.firstPos.x>1630 :
                    self.firstPos = 1630
                if self.firstPos.x<80 :
                    self.firstPos = 80
                if self.firstPos.x>1630 :
                    self.firstPos = 1630
                else:
                    dc.DrawRectangle(self.firstPos.x,30,self.secondPos.x-self.firstPos.x,240)
                self.haveDraw = 1
    
        #标签界面
        def OnLabelMove(self,event):
            pos=event.GetPosition()
            #在按下左键拖动后绘制两条指示线
            if event.Dragging() and event.LeftIsDown():
                self.labelPanel.Refresh()
                self.wavPanel.Refresh()
                self.labelPosition=event.GetPosition()
                a=self.wavTime*self.calPosition(pos.x,self.wavParams,self.wavLength,1)
                self.timeCtrl.SetValue("%.3fs"%a)
                dc=wx.ClientDC(self.labelPanel)
                dc.DrawLine(self.labelPosition.x,30,self.labelPosition.x,70)
                dc3=wx.BufferedDC(wx.ClientDC(self.wavPanel))
                #dc3=wx.BufferedPaintDC(self.wavPanel)
                dc3.DrawLine(self.labelPosition.x,30,self.labelPosition.x,270)
    
        #松开左键后绘制两条指示线
        def OnLabelDrawLine(self,event):
            self.labeltime=self.timeCtrl.GetValue()
            dc1 = wx.ClientDC(self.labelPanel)
            dc1.DrawLine(self.labelPosition.x, 30, self.labelPosition.x, 70)
            dc3 = wx.BufferedDC(wx.ClientDC(self.wavPanel))
            #dc3=wx.BufferedPaintDC(self.wavPanel)
            dc3.DrawLine(self.labelPosition.x, 30, self.labelPosition.x,270)
    
        #创建输入标签的文本框
        def OnLabelCreate(self,event):
            self.labelPos.append(self.labelPosition.x)
            self.labelPos.sort()
            self.labelCtrl=wx.TextCtrl(self.labelPanel,-1,"",pos=(self.labelPosition.x-93,33),size=(90,33),style=wx.TE_PROCESS_ENTER)
            self.labelCtrl.Bind(wx.EVT_TEXT_ENTER,self.TestEnter,self.labelCtrl)
            self.labellist.append((str(self.labeltime),self.labelCtrl))
        #标签文本框的enter建回调函数,若有值则保存,若无值按下回车则删除
        def TestEnter(self,event):
            self.labellist.sort()
            notfind=0
            enter_str=event.GetString()
            label=event.GetEventObject()
            for j in range(len(self.labellist)):
                if label == self.labellist[j][1]:
                    labelindex = j
                    itemtime = self.labellist[j][0]
            if enter_str == "":
                for i in range(len(self.labellist)):
                    if label == self.labellist[i][1]:
                        del self.labellist[i]
                        del self.labelPos[i]
                        self.showlist.DeleteItem(i)
                        label.Destroy()
                        break
            else:
                if self.showlist.GetItemCount() != 0:
                    for i in range(self.showlist.GetItemCount()):
                        if self.showlist.GetItem(i,0).GetText() == itemtime:
                            self.showlist.SetStringItem(i, 1, label.GetValue())
                            notfind=1
                            break
                    if notfind == 0:
                        index = self.showlist.InsertStringItem(labelindex, itemtime)
                        self.showlist.SetStringItem(index, 1, label.GetValue())
                else:
                    index = self.showlist.InsertStringItem(labelindex, str(self.labellist[0][0]))
                    self.showlist.SetStringItem(index, 1, self.labellist[0][1].GetValue())
            self.bbbPanel.Refresh()
    
        #创建标签显示的list界面,显示当前插入的标签的时间和内容
        def CreateLabelListUI(self):
            self.listbox=wx.BoxSizer(wx.HORIZONTAL)
            self.showlist = wx.ListCtrl(self.bbbPanel, -1, style=wx.LC_REPORT|wx.LC_SORT_ASCENDING)#wx.LC_REPORT|
            self.showlist.InsertColumn(0, u'时间', width=200)
            self.showlist.InsertColumn(1, u'标签', width=410)
            for i in self.labellist:
                index = self.showlist.InsertStringItem(sys.maxint, str(i[0]))
                label_str = i[1].GetValue()
                print label_str
                self.showlist.SetStringItem(index, 1, label_str)
            self.listbox.Add(self.showlist,1,wx.EXPAND)
            self.bbbPanel.SetSizerAndFit(self.listbox)
            self.bbbPanel.Refresh()
    
        #插销上一步的剪辑操作,实际为读取再前一次的缓存音频
        def testtest(self,event):
            print self.labellist
            self.cutCount = self.cutCount - 2
            if self.cutCount == 0:
                self.cutCount = 1
                data = self.list.GetItem(self.choosenItem,0)
                tuple_temp = self.wavList[int(data.GetText())-1]
                self.wavfilepath=tuple_temp[1]
                if len(self.tempwavlist) != 0:
                    self.tempwavlist.pop()
                print self.tempwavlist
                # self.cutCount = self.cutCount + 1
                self.drawBackJpg(self.wavfilepath)
                self.InitMedia()
                self.wavPanel.Refresh()
            else:
                print os.path.split(self.wavfilepath)
                path_str=os.path.split(self.wavfilepath)
                cutfile="temp"+str(self.cutCount)+".wav"
                temppath=os.path.join(path_str[0],cutfile)
                print temppath
                self.cutCount = self.cutCount + 1
                self.wavfilepath=temppath
                self.tempwavlist.pop()
                print self.tempwavlist
                self.drawBackJpg(self.wavfilepath)
                self.InitMedia()
                self.wavPanel.Refresh()
    
        #播放选中部分音频
        def PlayWav(self,event):
            f = wave.open(self.wavfilepath,"rb")
            print "1.pos:",self.firstPos.x,"2.pos",self.secondPos.x
            if self.firstPos.x < self.secondPos.x:
                x1=self.firstPos.x
                x2=self.secondPos.x
            else:
                x2=self.firstPos.x
                x1=self.secondPos.x
            print "x1:",x1,"x2",x2
            params = f.getparams()
            nchannels, sampwidth, framerate, nframes = params[:4]
            str_data = f.readframes(nframes)
            str_length = len(str_data)
            print "str length = ",str_length
            a=self.calPosition(x1,params,str_length,1)
            b=self.calPosition(x2,params,str_length,1)
            atime=round(a*self.wavTime,2)
            btime=round(b*self.wavTime,2)
            print atime,btime
            alength=int(a*self.mc.Length())
            print alength
            self.mc.Seek(alength)
            self.mc.Play()
            time.sleep(btime-atime)
            self.mc.Stop()
            # str_test=str_data[a:b]
            # print len(str_test)
    
            # p = pyaudio.PyAudio()
            # print f.getnchannels();
            # print p.get_format_from_width(f.getsampwidth())
            # print f.getframerate()
            # stream = p.open(format = p.get_format_from_width(f.getsampwidth()),
            #                 channels = f.getnchannels(),
            #                 rate = f.getframerate(),
            #                 output = True)
            # print "==="
            # stream.write(str_test)
    
            # stream.stop_stream()
            # stream.close()
            # f.close()
    
            # p.terminate()
    
        #剪辑音频
        def cutWav(self,event):
            print self.wavfilepath
            f = wave.open(self.wavfilepath,"rb")
            print os.path.split(self.wavfilepath)
            path_str=os.path.split(self.wavfilepath)
            cutfile="temp"+str(self.cutCount)+".wav"
            temppath=os.path.join(path_str[0],cutfile)
            print ("debug: temppath:", temppath)
            self.cutCount = self.cutCount + 1
            self.tempwavlist.append(temppath)
            print self.tempwavlist
            self.wavfilepath = temppath
            print "1.pos:",self.firstPos.x,"2.pos",self.secondPos.x
            if self.firstPos.x < self.secondPos.x:
                x1=self.firstPos.x
                x2=self.secondPos.x
            else:
                x2=self.firstPos.x
                x1=self.secondPos.x
            print "x1:",x1,"x2",x2
            params = f.getparams()
            nchannels, sampwidth, framerate, nframes = params[:4]
            str_data  = f.readframes(nframes)
            str_length = len(str_data)
            print "str length",str_length
            a=self.calPosition(x1,params,str_length,0)
            b=self.calPosition(x2,params,str_length,0)
            wf = wave.open(self.wavfilepath,"wb")
            wf.setnchannels(nchannels)
            wf.setsampwidth(sampwidth)
            wf.setframerate(framerate)
            str_test=str_data[0:a]+str_data[b:str_length]
            print len(str_test)
            wf.writeframes(str_test)
            wf.close()
            self.drawBackJpg(self.wavfilepath)
            self.InitMedia()
            self.wavPanel.Refresh()
        #计算当前坐标的在音频中的相对位置
        def calPosition(self,x,params,str_length,type):
            nchannels, sampwidth, framerate, nframes = params[:4]
            print nchannels, sampwidth, framerate, nframes
            bytecount=int(nchannels*sampwidth)
            print bytecount
            real_length = int(((str_length//bytecount)/framerate)/((((str_length//bytecount)/framerate)//0.5+1)*0.5)*1550)
            print real_length
            aa=(x-79)/real_length
            print aa
            a = ((str_length//bytecount)//1000)*(int(((x-79)/real_length)*1000))*bytecount
            print a
            if type == 1:
                # print "aa ",int(aa)
                return aa
            else:
                # print "a",int(a)
                return int(a)
        #绘制波形图片
        def drawBackJpg(self, path):
            print ("debug path:", path)
            f = wave.open(path, "r")
            params = f.getparams()
            nchannels, sampwidth, framerate, nframes = params[:4]
            str_data = f.readframes(nframes)
            f.close()
            str_length = len(str_data)
            self.wavLength = str_length
            self.wavParams = params
            time_limit=(((str_length//(nchannels*sampwidth)/framerate)//0.5+1)*0.5)
            wave_data = numpy.fromstring(str_data,dtype = numpy.short)
            wave_data.shape = -1, int(params[0])
            wave_data = wave_data.T
            time = numpy.arange(0, nframes)*(1.0/framerate)
            len_time = len(time)
            time = time[0:len_time]
            self.wavTime = len(time)/16000
            axes = pl.subplot(111)
            axes.plot(time, wave_data[0], 'cornflowerblue')
            axes.xaxis.set_ticks_position('top')
            axes.xaxis.set_major_locator(xmajorLocator)
            axes.xaxis.set_minor_locator(xminorLocator)
            axes.xaxis.grid(True, which='minor')
            axes.set_xlim([0.0, time_limit])
            axes.set_yticks([])
            fig = pl.gcf()
            fig.set_size_inches(20, 3)
            fig.savefig('mic4_output.png', dpi=100)
            # gc.collect()
            pl.close()
    
        def record_and_drawBackJpg(self, msg):
            global input_filename
            self.wavfilepath = input_filename
            self.OnFreshUI()   # 里面执行了, self.drawBackJpg(self.wavfilepath)
    
            # 重绘
            brush = wx.Brush("white")
            img = wx.Bitmap("mic4_output.png")
            dc = wx.ClientDC(self.wavPanel)
            dc.Clear()
            dc.SetBackground(brush)
            dc.DrawBitmap(img, -172, 0)
    
    
    
        def OnPaint2(self, event):
    
            mythread = threading.Thread(target=self.thread_paint)
            mythread.start()
    
            event.GetEventObject().Disable()
    
    
        def thread_paint(self):
            len = int(11025 / 256 * 20)
            for i in range(len):
                self.get_audio()   # 实现一边录音,一边绘图
                # 绘图
                # self.record_and_drawBackJpg()
    
    
        def get_audio(self):
            global in_path
            global global_frames
            global wavCount
    
            CHUNK = 256
            FORMAT = pyaudio.paInt16
            CHANNELS = 1                # 声道数
            RATE = 11025                # 采样率
            RECORD_SECONDS = 3          # 每次录音 5s
            WAVE_OUTPUT_FILENAME = in_path
            p = pyaudio.PyAudio()
            stream = p.open(format=FORMAT,
                            channels=CHANNELS,
                            rate=RATE,
                            input=True,
                            frames_per_buffer=CHUNK)
            print("*"*10, u"start record: please speak in 5s")
            frames = global_frames
            for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
                data = stream.read(CHUNK)
                frames.append(data)
            print("*"*10, u"speak over
    ")
            global_frames = frames
    
            stream.stop_stream()
            stream.close()
            p.terminate()
    
            # ./input.wav
            wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
            wf.setnchannels(CHANNELS)
            wf.setsampwidth(p.get_sample_size(FORMAT))
            wf.setframerate(RATE)
            # 写wav
            wf.writeframes(b''.join(global_frames))
            wf.close()
    
            wavCount = wavCount + 1
            if wavCount == 10:
                global_frames = []
                wavCount = 0
            # 和主线程之间进行通信, 发送更新图片消息
            wx.CallAfter(pub.sendMessage, "update", msg=wavCount)
    
    # start
    class LoginWin(wx.Frame):
        def __init__(self,parent,title):
            super(LoginWin, self).__init__(parent, title=title, size=(590,150))
            self.InitUI()
            self.Centre()
            self.Show()
    
        def InitUI(self):
            self.LoginPanel = wx.Panel(self)
            hbox = wx.BoxSizer(wx.HORIZONTAL)
            fgs = wx.FlexGridSizer(2, 3, 10,10)
            wavListST = wx.StaticText(self.LoginPanel, label = u"音频列表")
            recTextST = wx.StaticText(self.LoginPanel, label = u"识别文本")
            ChooseButton1 = wx.Button(self.LoginPanel, label=u"选择")
            ChooseButton2 = wx.Button(self.LoginPanel, label=u"选择")
            ChooseButton1.Bind(wx.EVT_BUTTON, self.ReadList)
            ChooseButton2.Bind(wx.EVT_BUTTON, self.ReadText)
            self.ListTC= wx.TextCtrl(self.LoginPanel, style=wx.TE_READONLY)
            self.TextTC = wx.TextCtrl(self.LoginPanel, style=wx.TE_READONLY)
            fgs.AddMany([(wavListST), (self.ListTC, 1, wx.EXPAND), (ChooseButton1), (recTextST),(self.TextTC, 1, wx.EXPAND), (ChooseButton2)])
            fgs.AddGrowableCol(1, 1)
            hbox.Add(fgs, proportion = 1, flag = wx.ALL|wx.EXPAND, border = 10)
            OkButton = wx.Button(self.LoginPanel, label="OK")
            CancelButton = wx.Button(self.LoginPanel, label="CANCEL")
            OkButton.Bind(wx.EVT_BUTTON, self.OnClick)
            sizer = wx.GridBagSizer(hgap=10, vgap=10)
            sizer.Add(OkButton, pos=(0, 20), flag=wx.ALL)
            sizer.Add(CancelButton, pos=(0, 21), flag=wx.ALL)
            bsizer = wx.BoxSizer(wx.VERTICAL)
            bsizer.Add(hbox,0,wx.EXPAND,10)
            bsizer.Add(sizer,0,wx.EXPAND,10)
            self.LoginPanel.SetSizerAndFit(bsizer)
            sizer.SetSizeHints(self.LoginPanel)
    
        def ReadList(self, event):
            dlg = wx.FileDialog(self, message=u"选择音频列表文件select ",defaultDir=os.getcwd(),defaultFile="",style=wx.OPEN|wx.CHANGE_DIR)
            self.wavList = ["mic4.wav"]
            if dlg.ShowModal() == wx.ID_OK:
                path = dlg.GetPath()
                self.ListTC.SetValue(path)
                print ("Debug: ", path)
                # self.wavList = self.ReadFilePath(path)
            dlg.Destroy()
    
        def ReadText(self, event):
            dlg = wx.FileDialog(self, message=u"选择识别结果文本",defaultDir=os.getcwd(), defaultFile="",style = wx.OPEN|wx.CHANGE_DIR)
            self.recText = ["recog.txt"]
            if dlg.ShowModal() == wx.ID_OK:
                path = dlg.GetPath()
                self.TextTC.SetValue(path)
                # self.recText = se0lf.ReadFilePath(path)
                print ("debug: rectext:", self.recText)
            dlg.Destroy()
    
        def ReadFilePath(self,path):
            tempList = []
            i = 1
            with open(path, 'rb') as f:
                for line in f.readlines():
                    tempList.append((i, line.strip('
    ').decode('utf-8')))
                    i = i + 1
            return tempList
    
        def OnClick(self, event):
            self.Close()
            mainWin = MyFrame(self.wavList, self.recText)
            mainWin.Show()
    
    
    if __name__ == '__main__':
    
        app = wx.App(0)
    
        LoginWin(None, 'login')
    
        app.MainLoop()

    可以通过这个简短的例子, 学习, 线程间通信: https://www.cnblogs.com/douzujun/p/10719458.html

    主要流程是: 点击按钮, 执行按钮点击事件函数(录音), 函数里开启一个线程, 同时向主线程发送消息, 主线程接收消息, 将消息发给绘图函数, 让其执行

  • 相关阅读:
    Java多线程详解——一篇文章搞懂Java多线程
    解析spring事务管理@Transactional为什么要添加rollbackFor=Exception.class(事务失效)
    有参构造器(方法)和无参构造器(方法)的作用(区别)
    JAVA:将类、抽象类、接口当成方法的参数传入
    为什么要有无参构造方法,无参构造的运行原理
    java 如何在listener(监听器) 中使用Spring容器管理bean
    java为什么有些异常throw出去需要在函数头用throws声明,一些就不用?
    用mmap 考os不用考虑, 利用 cache 向量化计算 内存对齐 叶大小 都得考虑 还有原子写入
    位运算 异或 数组中数字出现的次数 II
    程序中有个常量,空间超过了1页,有哪些优化思路
  • 原文地址:https://www.cnblogs.com/douzujun/p/10722487.html
Copyright © 2020-2023  润新知