#!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多线程通信的应用-实现边录音边绘制音谱图的更多相关文章

  1. 关于wxpython多线程研究包括(import Publisher错误研究)

    作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况 ...

  2. 关于wxpython多线程研究包括(import Publisher等错误研究)

    作为一个自动化测试人员,开发基本的应用桌面程序是必须的!最近在研究wxpython相关知识,目前看到多线程一块,发现官方文档介绍说:"在线程中不能修改修改窗口属性!",但是实际情况 ...

  3. Android多线程通信机制

    掌握Android的多线程通信机制,我们首先应该掌握Android中进程与线程是什么. 1. 进程 在Android中,一个应用程序就是一个独立的进程(应用运行在一个独立的环境中,可以避免其他应用程序 ...

  4. 转:windows下多线程通信方法

    多线程知识简介 同一进程中可以包含多个线程,由于进程中的多个线程可以共享进程中的资源,所以使同一进程中的多个线程之间通信相对比较简单. 当需要有多个线程来访问一个全局变量时,通常我们会在这个全局变量前 ...

  5. JAVA多线程通信

    JAVA多线程通信 package com.frank.thread; /** * author:pengyan * date:Jun 16, 2011 * file:ProducerAndCusto ...

  6. 多线程通信的两种方式? (可重入锁ReentrantLock和Object)

    (一)Java中线程协作的最常见的两种方式: (1)利用Object的wait().notify()和notifyAll()方法及synchronized (2)使用Condition.Reentra ...

  7. 8.并发编程--多线程通信-wait-notify-模拟Queue

    并发编程--多线程通信-wait-notify-模拟Queue 1. BlockingQueue 顾名思义,首先是一个队列,其次支持阻塞的机制:阻塞放入和获取队列中的数据. 如何实现这样一个队列: 要 ...

  8. 7.并发编程--多线程通信-wait-notify

    并发编程--多线程通信-wait-notify 多线程通信:线程通信的目的是为了能够让线程之间相互发送信号; 1. 多线程通信: 线程通信的目的是为了能够让线程之间相互发送信号.另外,线程通信还能够使 ...

  9. 母鸡下蛋实例:多线程通信生产者和消费者wait/notify和condition/await/signal条件队列

    简介 多线程通信一直是高频面试考点,有些面试官可能要求现场手写生产者/消费者代码来考察多线程的功底,今天我们以实际生活中母鸡下蛋案例用代码剖析下实现过程.母鸡在鸡窝下蛋了,叫练从鸡窝里把鸡蛋拿出来这个 ...

随机推荐

  1. Hexo自定义页面的方法

    原文转自:http://refined-x.com/2017/07/10/Hexo%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A1%B5%E9%9D%A2%E7%9A%84%E6%9 ...

  2. Java多线程与并发相关问题

    1.什么是线程? 2.线程和进程有什么区别? 3.如何在Java中实现线程? 4.Java关键字volatile与synchronized作用与区别? volatile修饰的变量不保留拷贝,直接访问主 ...

  3. Django contenttypes 组件

    contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Conte ...

  4. RabbitMQ集群搭建和使用

    一.环境准备 1.选择RabbitMQ的版本 http://www.rabbitmq.com/changelog.html 注: 不同版本的Linux选择的RabbitMQ版本也不同,参照 http: ...

  5. 重建二叉树[by Python]

    题目: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2 ...

  6. Spring Security(三十三):10.3 Password Encoding

    Spring Security’s PasswordEncoder interface is used to support the use of passwords which are encode ...

  7. leetcode 263. Ugly Number 、264. Ugly Number II 、313. Super Ugly Number 、204. Count Primes

    263. Ugly Number 注意:1.小于等于0都不属于丑数 2.while循环的判断不是num >= 0, 而是能被2 .3.5整除,即能被整除才去除这些数 class Solution ...

  8. PWC6345: There is an error in invoking javac. A full JDK (not just JRE) is required

    今天在使用jetty运行一个项目的时候报这个错误,仔细看了下,应该是eclipse配置的jdk或者jre出错. 看了下环境变量,发现有些配置没有配置完全. 我个人的解决方法: 在path中,添加%JA ...

  9. Emit动态代理.NetCore迁移之旅

    [前言] 前面我们介绍了Aop 从静态代理到动态代理:https://www.cnblogs.com/7tiny/p/9657451.html 我们在.NetFramework平台下使用微软提供的Em ...

  10. 动态链接库-Win32 DLL的说明

    在实际编程时,我们可以把完成某种功能的函数放在一个动态链接库中,然后给其他程序调用. WinAPI中所有的函数都包含在3个最重要的DLL中. Kernel32.dll 它包含那些用于管理内存.进程和线 ...