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"&▷\tF1")
self.buttonPause=wx.Button(self.annoPanel,label=u"&‖\tEsc")
self.buttonStop=wx.Button(self.annoPanel,label=u"&■\tCtrl-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\n")
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('\n').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
主要流程是: 点击按钮, 执行按钮点击事件函数(录音), 函数里开启一个线程, 同时向主线程发送消息, 主线程接收消息, 将消息发给绘图函数, 让其执行
wxpython多线程通信的应用-实现边录音边绘制音谱图的更多相关文章
- 关于wxpython多线程研究包括(import Publisher错误研究)
作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况 ...
- 关于wxpython多线程研究包括(import Publisher等错误研究)
作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况 ...
- Android多线程通信机制
掌握Android的多线程通信机制,我们首先应该掌握Android中进程与线程是什么. 1. 进程 在Android中,一个应用程序就是一个独立的进程(应用运行在一个独立的环境中,可以避免其他应用程序 ...
- 转:windows下多线程通信方法
多线程知识简介 同一进程中可以包含多个线程,由于进程中的多个线程可以共享进程中的资源,所以使同一进程中的多个线程之间通信相对比较简单. 当需要有多个线程来访问一个全局变量时,通常我们会在这个全局变量前 ...
- JAVA多线程通信
JAVA多线程通信 package com.frank.thread; /** * author:pengyan * date:Jun 16, 2011 * file:ProducerAndCusto ...
- 多线程通信的两种方式? (可重入锁ReentrantLock和Object)
(一)Java中线程协作的最常见的两种方式: (1)利用Object的wait().notify()和notifyAll()方法及synchronized (2)使用Condition.Reentra ...
- 8.并发编程--多线程通信-wait-notify-模拟Queue
并发编程--多线程通信-wait-notify-模拟Queue 1. BlockingQueue 顾名思义,首先是一个队列,其次支持阻塞的机制:阻塞放入和获取队列中的数据. 如何实现这样一个队列: 要 ...
- 7.并发编程--多线程通信-wait-notify
并发编程--多线程通信-wait-notify 多线程通信:线程通信的目的是为了能够让线程之间相互发送信号; 1. 多线程通信: 线程通信的目的是为了能够让线程之间相互发送信号.另外,线程通信还能够使 ...
- 母鸡下蛋实例:多线程通信生产者和消费者wait/notify和condition/await/signal条件队列
简介 多线程通信一直是高频面试考点,有些面试官可能要求现场手写生产者/消费者代码来考察多线程的功底,今天我们以实际生活中母鸡下蛋案例用代码剖析下实现过程.母鸡在鸡窝下蛋了,叫练从鸡窝里把鸡蛋拿出来这个 ...
随机推荐
- python_库学习_02_微信自动回复机器人
一.python发展的趋势日益庞大,微信也有对应的库itchat.这次的实例做做成可在任意电脑运行的微信自动回复机器人exe.文件. 二.完成这个小应用我们需要装一些库,, itchat:这个东东不出 ...
- LeetCode算法题-Longest Uncommon Subsequence I(Java实现)
这是悦乐书的第252次更新,第265篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第119题(顺位题号是521).给定一组两个字符串,您需要找到这组两个字符串中最长的不同 ...
- Python开发【内置模块篇】os模块
1.当前路径及路径下的文件 os.getcwd():查看当前所在路径. >>> import os >>> os.getcwd() 'E:\\test' >& ...
- maven eclipse web 项目 问题 cannot change version of project facet dynamic web module to 3.0
cannot change version of project facet dynamic web module to 3.0 修改 web.xml 头部 xsi:schemaLocation=&q ...
- Python-序列号和模块复习-64
# 序列化模块 # 数据类型转化成字符串的过程就是序列化 # 为了方便存储和网络传输 # json # dumps # loads # dump 和文件有关 # load load不能load多次 i ...
- mybatis 使用缓存策略
mybatis中默认开启缓存 1.mybatis中,默认是开启缓存的,缓存的是一个statement对象. 不同情况下是否会使用缓存 同一个SqlSession对象,重复调用同一个id的<sel ...
- 桌面应用之electron开发与转换
桌面应用之electron开发与转换 一,介绍与需求 1.1,介绍 1. Electron简介 Electron是用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Ele ...
- final关键字总结
参考文章[https://www.cnblogs.com/xrq730/p/4820296.html] 前言:在Java中final作为最常见的一个关键字,平常用到的地方也很多,接下来就来看看什么是f ...
- Linux(Ubuntu)使用日记(三)------git安装使用
1. 安装 首先,确认你的系统是否已安装git,可以通过git指令进行查看,如果没有,在命令行模式下输入sudo apt-get install git命令进行安装. 2. 配置 git confi ...
- Maven 建立的项目resource对应的实际位置
如图,springmvc-servlet.xml在项目中实际位置为: WEB-INF/classes/config/springmvc/springmvc-servlet.xml 在配置项 ...