mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-26 07:04:12 +08:00
mem
This commit is contained in:
parent
ee183936b7
commit
11f370042f
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,3 +1,9 @@
|
||||
[submodule "plugins/libs/wil"]
|
||||
path = plugins/libs/wil
|
||||
url = https://github.com/microsoft/wil.git
|
||||
[submodule "plugins/libs/tinymp3"]
|
||||
path = plugins/libs/tinymp3
|
||||
url = https://github.com/HIllya51/tinymp3
|
||||
[submodule "plugins/libs/miniaudio"]
|
||||
path = plugins/libs/miniaudio
|
||||
url = https://github.com/HIllya51/miniaudio
|
||||
|
@ -16,9 +16,9 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
from PyQt5.QtGui import QPixmap, QImage
|
||||
from traceback import print_exc
|
||||
import requests, json, subprocess, time
|
||||
from PyQt5.QtCore import pyqtSignal, Qt, QUrl
|
||||
import qtawesome, functools, os, base64
|
||||
import requests, json, time
|
||||
from PyQt5.QtCore import pyqtSignal, Qt
|
||||
import qtawesome, functools, os, base64, winsharedutils
|
||||
import gobject, uuid, windows, platform
|
||||
from myutils.config import globalconfig, _TR, static_data
|
||||
import myutils.ankiconnect as anki
|
||||
@ -33,38 +33,12 @@ from gui.usefulwidget import (
|
||||
getcolorbutton,
|
||||
tabadd_lazy,
|
||||
)
|
||||
from myutils.subproc import subproc_w, autoproc
|
||||
|
||||
from myutils.subproc import subproc_w
|
||||
from myutils.wrapper import threader
|
||||
from myutils.ocrutil import imageCut, ocr_run
|
||||
from gui.rangeselect import rangeselct_function
|
||||
|
||||
|
||||
class ffmpeg_virtual_audio_capturer:
|
||||
def __init__(self):
|
||||
os.makedirs("./cache/tts", exist_ok=True)
|
||||
self.file = os.path.abspath(
|
||||
os.path.join("./cache/tts", str(time.time()) + ".mp3")
|
||||
)
|
||||
try:
|
||||
self.engine = subprocess.Popen(
|
||||
os.path.join(
|
||||
globalconfig["ffmpeg"],
|
||||
f'ffmpeg.exe -f dshow -i audio="virtual-audio-capturer" "{self.file}"',
|
||||
),
|
||||
stdin=subprocess.PIPE,
|
||||
)
|
||||
except:
|
||||
print_exc()
|
||||
|
||||
def end(self):
|
||||
try:
|
||||
self.engine.stdin.write(b"q")
|
||||
self.engine.stdin.flush()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
class loopbackrecorder:
|
||||
def __init__(self):
|
||||
os.makedirs("./cache/tts", exist_ok=True)
|
||||
@ -72,26 +46,37 @@ class loopbackrecorder:
|
||||
os.path.join("./cache/tts", str(time.time()) + ".wav")
|
||||
)
|
||||
try:
|
||||
if platform.architecture()[0] == "64bit":
|
||||
_6432 = "64"
|
||||
elif platform.architecture()[0] == "32bit":
|
||||
_6432 = "32"
|
||||
self.waitsignal = str(time.time())
|
||||
self.engine = autoproc(
|
||||
subproc_w(
|
||||
'./files/plugins/shareddllproxy{}.exe recordaudio "{}" "{}"'.format(
|
||||
_6432, self.file, self.waitsignal
|
||||
),
|
||||
name="recordaudio",
|
||||
)
|
||||
self.engine = subproc_w(
|
||||
'./files/plugins/shareddllproxy32.exe recordaudio "{}" "{}"'.format(
|
||||
self.file, self.waitsignal
|
||||
),
|
||||
)
|
||||
except:
|
||||
print_exc()
|
||||
|
||||
def end(self):
|
||||
@threader
|
||||
def end(self, callback):
|
||||
windows.SetEvent(
|
||||
windows.AutoHandle(windows.CreateEvent(False, False, self.waitsignal))
|
||||
)
|
||||
self.engine.wait()
|
||||
filewav = self.file
|
||||
if os.path.exists(filewav) == False:
|
||||
callback("")
|
||||
return
|
||||
filemp3 = filewav.replace(".wav", ".mp3")
|
||||
subproc_w(
|
||||
'./files/plugins/shareddllproxy32.exe mainmp3 "{}" "{}"'.format(
|
||||
filewav, filemp3
|
||||
),
|
||||
run=True,
|
||||
)
|
||||
if os.path.exists(filemp3):
|
||||
os.remove(filewav)
|
||||
callback(filemp3)
|
||||
else:
|
||||
callback(filewav)
|
||||
|
||||
|
||||
class statusbutton(QPushButton):
|
||||
@ -390,49 +375,13 @@ class AnkiWindow(QWidget):
|
||||
getsimpleswitch(globalconfig["ankiconnect"], "autoruntts"),
|
||||
)
|
||||
|
||||
layout.addWidget(QLabel())
|
||||
layout.addRow(_TR("录音"), QLabel())
|
||||
lb = QLabel()
|
||||
lb.setOpenExternalLinks(True)
|
||||
lb.setText(
|
||||
'<a href="https://github.com/HIllya51/RESOURCES/releases/download/softwares/virtual-audio.zip">virtual-audio-capturer</a>'
|
||||
)
|
||||
layout.addRow(_TR("安装录音驱动"), lb)
|
||||
ffmpegpath = getlineedit(globalconfig, "ffmpeg", readonly=True)
|
||||
|
||||
def selectpath():
|
||||
f = QFileDialog.getExistingDirectory()
|
||||
if f != "":
|
||||
ffmpegpath.setText(f)
|
||||
|
||||
layout.addRow(
|
||||
_TR("ffmpeg"),
|
||||
getboxlayout(
|
||||
[
|
||||
ffmpegpath,
|
||||
getcolorbutton(
|
||||
"",
|
||||
"",
|
||||
selectpath,
|
||||
icon="fa.gear",
|
||||
constcolor="#FF69B4",
|
||||
),
|
||||
],
|
||||
makewidget=True,
|
||||
),
|
||||
)
|
||||
|
||||
return wid
|
||||
|
||||
def startorendrecord(self, target: QLineEdit, idx):
|
||||
if idx == 1:
|
||||
if len(globalconfig["ffmpeg"]) and os.path.exists(globalconfig["ffmpeg"]):
|
||||
self.recorder = ffmpeg_virtual_audio_capturer()
|
||||
else:
|
||||
self.recorder = loopbackrecorder()
|
||||
self.recorder = loopbackrecorder()
|
||||
else:
|
||||
self.recorder.end()
|
||||
target.setText(self.recorder.file)
|
||||
self.recorder.end(callback=target.setText)
|
||||
|
||||
def createaddtab(self):
|
||||
layout = QVBoxLayout()
|
||||
|
@ -20,8 +20,9 @@ from myutils.config import (
|
||||
savehook_new_data,
|
||||
getdefaultsavehook,
|
||||
)
|
||||
from ctypes import c_float, pointer, c_void_p
|
||||
import threading
|
||||
import re, heapq
|
||||
import re, heapq, winsharedutils
|
||||
from myutils.vndb import searchfordata, getvidbytitle
|
||||
from myutils.wrapper import tryprint
|
||||
|
||||
@ -260,48 +261,36 @@ class wavmp3player:
|
||||
if task is None:
|
||||
continue
|
||||
binary, volume, force = task
|
||||
os.makedirs("./cache/tts", exist_ok=True)
|
||||
durationms = self._playsoundWin(binary, volume)
|
||||
|
||||
tgt = os.path.abspath("./cache/tts/" + str(time.time()) + ".wav")
|
||||
with open(tgt, "wb") as ff:
|
||||
ff.write(binary)
|
||||
durationms = self._playsoundWin(tgt, volume)
|
||||
self.lastfile = tgt
|
||||
if durationms and globalconfig["ttsnointerrupt"]:
|
||||
while durationms > 0:
|
||||
durationms -= 100
|
||||
time.sleep(0.1)
|
||||
if self.tasks and self.tasks[-1]:
|
||||
break
|
||||
# time.sleep(durationms / 1000)
|
||||
except:
|
||||
print_exc()
|
||||
|
||||
def _playsoundWin(self, sound, volume):
|
||||
def _playsoundWin(self, binary, volume):
|
||||
try:
|
||||
|
||||
windows.mciSendString(("stop lunatranslator_mci_{}".format(self.i)))
|
||||
windows.mciSendString(("close lunatranslator_mci_{}".format(self.i)))
|
||||
self.i += 1
|
||||
duration = c_float()
|
||||
device = c_void_p()
|
||||
decoder = c_void_p()
|
||||
succ = winsharedutils.PlayAudioInMem(
|
||||
binary,
|
||||
len(binary),
|
||||
volume / 100,
|
||||
pointer(decoder),
|
||||
pointer(device),
|
||||
pointer(duration),
|
||||
)
|
||||
if succ != 0:
|
||||
return 0
|
||||
if self.lastfile:
|
||||
os.remove(self.lastfile)
|
||||
self.lastfile = sound
|
||||
windows.mciSendString(
|
||||
'open "{}" type mpegvideo alias lunatranslator_mci_{}'.format(
|
||||
sound, self.i
|
||||
)
|
||||
)
|
||||
durationms = int(
|
||||
windows.mciSendString(
|
||||
"status lunatranslator_mci_{} length".format(self.i)
|
||||
)
|
||||
)
|
||||
windows.mciSendString(
|
||||
"setaudio lunatranslator_mci_{} volume to {}".format(
|
||||
self.i, volume * 10
|
||||
)
|
||||
)
|
||||
windows.mciSendString(("play lunatranslator_mci_{}".format(self.i)))
|
||||
winsharedutils.PlayAudioInMem_Stop(self.lastfile[0], self.lastfile[1])
|
||||
self.lastfile = decoder, device
|
||||
durationms = duration.value * 1000
|
||||
except:
|
||||
durationms = 0
|
||||
|
||||
|
@ -16,6 +16,7 @@ from ctypes import (
|
||||
create_string_buffer,
|
||||
c_size_t,
|
||||
windll,
|
||||
c_float,
|
||||
c_char,
|
||||
)
|
||||
from ctypes.wintypes import WORD, HANDLE, HWND, LONG, DWORD
|
||||
@ -186,7 +187,10 @@ html_release.argtypes = (c_void_p,)
|
||||
html_get_current_url = utilsdll.html_get_current_url
|
||||
html_get_current_url.argtypes = c_void_p, c_wchar_p
|
||||
html_set_html = utilsdll.html_set_html
|
||||
html_set_html.argtypes = c_void_p, c_wchar_p,
|
||||
html_set_html.argtypes = (
|
||||
c_void_p,
|
||||
c_wchar_p,
|
||||
)
|
||||
|
||||
|
||||
class HTMLBrowser:
|
||||
@ -333,3 +337,17 @@ startmaglistener = utilsdll.startmaglistener
|
||||
startmaglistener.restype = HANDLE
|
||||
endmaglistener = utilsdll.endmaglistener
|
||||
endmaglistener.argtypes = (HANDLE,)
|
||||
|
||||
PlayAudioInMem = utilsdll.PlayAudioInMem
|
||||
PlayAudioInMem.argtypes = (
|
||||
c_void_p,
|
||||
c_size_t,
|
||||
c_float,
|
||||
c_void_p,
|
||||
c_void_p,
|
||||
POINTER(c_float),
|
||||
)
|
||||
PlayAudioInMem.restype = c_int
|
||||
|
||||
PlayAudioInMem_Stop = utilsdll.PlayAudioInMem_Stop
|
||||
PlayAudioInMem_Stop.argtypes = c_void_p, c_void_p
|
||||
|
@ -54,7 +54,6 @@
|
||||
"changecharset": false,
|
||||
"changecharset_charset": 2
|
||||
},
|
||||
"ffmpeg": "",
|
||||
"requestinterval": 1,
|
||||
"keepontop": true,
|
||||
"buttonsize": 20,
|
||||
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "التعرف الضوئي على الحروف",
|
||||
"优先级": "الأولوية",
|
||||
"编码": "ترميز",
|
||||
"安装录音驱动": "تثبيت برنامج تشغيل التسجيل",
|
||||
"录音": "تسجيل صوتي",
|
||||
"自动TTS": "التلقائي تحويل النص إلى كلام",
|
||||
"使用webview显示": "عرض باستخدام WebView"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "截圖後進行OCR",
|
||||
"优先级": "優先順序",
|
||||
"编码": "編碼",
|
||||
"安装录音驱动": "安裝錄音驅動",
|
||||
"录音": "錄音",
|
||||
"自动TTS": "自動TTS",
|
||||
"使用webview显示": "使用webview顯示"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "Perform OCR after taking screenshots",
|
||||
"优先级": "priority",
|
||||
"编码": "coding",
|
||||
"安装录音驱动": "Install recording driver",
|
||||
"录音": "tape",
|
||||
"自动TTS": "Automatic TTS",
|
||||
"使用webview显示": "Display using webview"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "OCR después de la captura de pantalla",
|
||||
"优先级": "Prioridad",
|
||||
"编码": "Codificación",
|
||||
"安装录音驱动": "Instalación de la unidad de grabación",
|
||||
"录音": "Grabación",
|
||||
"自动TTS": "TTS automático",
|
||||
"使用webview显示": "Mostrar con Webview"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "OCR après capture d'écran",
|
||||
"优先级": "Priorité",
|
||||
"编码": "Codage",
|
||||
"安装录音驱动": "Installer le driver d'enregistrement",
|
||||
"录音": "Enregistrement sonore",
|
||||
"自动TTS": "Tts automatique",
|
||||
"使用webview显示": "Afficher avec webview"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "Esegui OCR dopo aver scattato screenshot",
|
||||
"优先级": "priorità",
|
||||
"编码": "codifica",
|
||||
"安装录音驱动": "Installa il driver di registrazione",
|
||||
"录音": "nastro",
|
||||
"自动TTS": "TTS automatico",
|
||||
"使用webview显示": "Visualizzazione tramite webview"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "スクリーンショット後にOCR",
|
||||
"优先级": "優先度",
|
||||
"编码": "エンコード",
|
||||
"安装录音驱动": "録音ドライブのインストール",
|
||||
"录音": "レコーディング",
|
||||
"自动TTS": "自動TTS",
|
||||
"使用webview显示": "webview表示の使用"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "캡처해서 OCR 진행하도록 하겠습니다.",
|
||||
"优先级": "우선 순위",
|
||||
"编码": "인코딩",
|
||||
"安装录音驱动": "녹음 드라이브 설치",
|
||||
"录音": "녹음",
|
||||
"自动TTS": "자동 TTS",
|
||||
"使用webview显示": "웹뷰를 사용하여 표시"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "Wykonanie OCR po wykonaniu zrzutów ekranu",
|
||||
"优先级": "priorytet",
|
||||
"编码": "kodowanie",
|
||||
"安装录音驱动": "Zainstaluj sterownik nagrywania",
|
||||
"录音": "taśma",
|
||||
"自动TTS": "Automatyczny TTS",
|
||||
"使用webview显示": "Wyświetlanie przy użyciu widoku internetowego"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "Снимок экрана после OCR",
|
||||
"优先级": "Приоритеты",
|
||||
"编码": "Код",
|
||||
"安装录音驱动": "Установка привода звукозаписи",
|
||||
"录音": "Запись",
|
||||
"自动TTS": "Автоматический TTS",
|
||||
"使用webview显示": "Использовать webview"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "ทำ OCR หลังจากจับภาพหน้าจอ",
|
||||
"优先级": "ลำดับความสำคัญ",
|
||||
"编码": "การเข้ารหัส",
|
||||
"安装录音驱动": "ติดตั้งไดรฟ์บันทึก",
|
||||
"录音": "การบันทึกเสียง",
|
||||
"自动TTS": "TTS อัตโนมัติ",
|
||||
"使用webview显示": "ใช้ webview เพื่อแสดงผล"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "Ekran fotoğraflarını aldıktan sonra OCR yap",
|
||||
"优先级": "Prioritet",
|
||||
"编码": "coding",
|
||||
"安装录音驱动": "Kayıt sürücüsünü kur",
|
||||
"录音": "kaset",
|
||||
"自动TTS": "Otomatik TTS",
|
||||
"使用webview显示": "Web görüntüsünü kullanarak göster"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "Виконати OCR після роботи знімків екрана",
|
||||
"优先级": "пріоритет",
|
||||
"编码": "кодування",
|
||||
"安装录音驱动": "Встановити драйвер запису",
|
||||
"录音": "стрічку",
|
||||
"自动TTS": "Автоматичний TTS",
|
||||
"使用webview显示": "Показувати за допомогою веб- перегляду"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "OCR sau khi chụp ảnh màn hình",
|
||||
"优先级": "Ưu tiên",
|
||||
"编码": "Mã hóa",
|
||||
"安装录音驱动": "Cài đặt Recording Drive",
|
||||
"录音": "Ghi âm",
|
||||
"自动TTS": "Tự động TTS",
|
||||
"使用webview显示": "Sử dụng WebView để hiển thị"
|
||||
}
|
@ -789,8 +789,6 @@
|
||||
"截图后进行OCR": "",
|
||||
"优先级": "",
|
||||
"编码": "",
|
||||
"安装录音驱动": "",
|
||||
"录音": "",
|
||||
"自动TTS": "",
|
||||
"使用webview显示": ""
|
||||
}
|
@ -29,7 +29,7 @@ include(generate_product_version)
|
||||
|
||||
set(VERSION_MAJOR 2)
|
||||
set(VERSION_MINOR 51)
|
||||
set(VERSION_PATCH 7)
|
||||
set(VERSION_PATCH 8)
|
||||
|
||||
add_library(pch pch.cpp)
|
||||
target_precompile_headers(pch PUBLIC pch.h)
|
||||
|
@ -8,6 +8,9 @@ include_directories(${CMAKE_CURRENT_LIST_DIR})
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/Detours-4.0.1/include)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/wil/include)
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/miniaudio)
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/tinymp3)
|
||||
|
||||
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 4)
|
||||
set(LTLPlatform "Win32")
|
||||
|
1
plugins/libs/miniaudio
Submodule
1
plugins/libs/miniaudio
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4a5b74bef029b3592c54b6048650ee5f972c1a48
|
1
plugins/libs/tinymp3
Submodule
1
plugins/libs/tinymp3
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 9781d63bf7d057457b25b5e77492bcf2cfa109c5
|
@ -12,17 +12,18 @@ generate_product_version(
|
||||
)
|
||||
|
||||
|
||||
add_executable(shareddllproxy applicationloopbackaudio/LoopbackCapture.cpp applicationloopbackaudio/runer.cpp shareddllproxy.cpp dllinject.cpp ntleas.cpp aspatch.cpp update.cpp ${versioninfo})
|
||||
add_executable(shareddllproxy shareddllproxy.cpp dllinject.cpp ntleas.cpp aspatch.cpp update.cpp ${versioninfo})
|
||||
target_precompile_headers(shareddllproxy REUSE_FROM pch)
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||
|
||||
target_link_libraries(shareddllproxy Mfplat mfuuid ${Detours})
|
||||
set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy64")
|
||||
else()
|
||||
add_library(tinymp3 ../libs/tinymp3/shine_mp3.c)
|
||||
add_subdirectory(voiceroid2)
|
||||
add_library(x86lib dreye.cpp jbj7.cpp kingsoft.cpp le.cpp neospeech.cpp ../implsapi.cpp LR.cpp)
|
||||
add_library(x86lib dreye.cpp jbj7.cpp kingsoft.cpp le.cpp neospeech.cpp ../implsapi.cpp LR.cpp applicationloopbackaudio/runer.cpp applicationloopbackaudio/LoopbackCapture.cpp mp3.cpp)
|
||||
target_precompile_headers(voiceroid2 REUSE_FROM pch)
|
||||
target_precompile_headers(x86lib REUSE_FROM pch)
|
||||
target_link_libraries(shareddllproxy Mfplat mfuuid x86lib voiceroid2 ${Detours})
|
||||
target_link_libraries(shareddllproxy Mfplat mfuuid x86lib tinymp3 voiceroid2 ${Detours})
|
||||
set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy32")
|
||||
endif()
|
||||
|
248
plugins/shareddllproxy/mp3.cpp
Normal file
248
plugins/shareddllproxy/mp3.cpp
Normal file
@ -0,0 +1,248 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <timing.h>
|
||||
#include <shine_mp3.h>
|
||||
|
||||
#define DR_WAV_IMPLEMENTATION
|
||||
|
||||
#include <dr_wav.h>
|
||||
|
||||
#define DR_MP3_IMPLEMENTATION
|
||||
|
||||
#include <dr_mp3.h>
|
||||
|
||||
void error(char *s);
|
||||
|
||||
|
||||
int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint32_t *channels, uint64_t *totalSampleCount) {
|
||||
int16_t *buffer = drwav_open_file_and_read_pcm_frames_s16(filename, channels, sampleRate, totalSampleCount, NULL);
|
||||
if (buffer == NULL) {
|
||||
drmp3_config pConfig;
|
||||
buffer = drmp3_open_file_and_read_pcm_frames_s16(filename, &pConfig, totalSampleCount, NULL);
|
||||
if (buffer != NULL) {
|
||||
*channels = pConfig.channels;
|
||||
*sampleRate = pConfig.sampleRate;
|
||||
*totalSampleCount *= *channels;
|
||||
} else {
|
||||
printf("read file [%s] error.\n", filename);
|
||||
}
|
||||
} else {
|
||||
*totalSampleCount *= *channels;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/* Some global vars. */
|
||||
char *infname, *outfname;
|
||||
FILE *outfile;
|
||||
int quiet = 0;
|
||||
int stereo = STEREO;
|
||||
int force_mono = 0;
|
||||
|
||||
/* Write out the MP3 file */
|
||||
int write_mp3(long bytes, void *buffer, void *config) {
|
||||
return fwrite(buffer, sizeof(unsigned char), bytes, outfile) / sizeof(unsigned char);
|
||||
}
|
||||
|
||||
/* Output error message and exit */
|
||||
void error(char *s) {
|
||||
fprintf(stderr, "Error: %s\n", s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void print_usage() {
|
||||
printf("Audio Processing\n");
|
||||
printf("mp3 encoder && decoder\n");
|
||||
printf("blog: http://cpuimage.cnblogs.com/\n");
|
||||
printf("Usage: tinymp3 [options] <infile> <outfile>\n\n");
|
||||
printf("Use \"-\" for standard input or output.\n\n");
|
||||
printf("Options:\n");
|
||||
printf(" -h this help message\n");
|
||||
printf(" -b <bitrate> set the bitrate [8-320], default 64 kbit\n");
|
||||
printf(" -m force encoder to operate in mono\n");
|
||||
printf(" -c set copyright flag, default off\n");
|
||||
printf(" -j encode in joint stereo (stereo data only)\n");
|
||||
printf(" -d encode in dual-channel (stereo data only)\n");
|
||||
printf(" -q quiet mode\n");
|
||||
}
|
||||
|
||||
/* Use these default settings, can be overridden */
|
||||
static void set_defaults(shine_config_t *config) {
|
||||
shine_set_config_mpeg_defaults(&config->mpeg);
|
||||
}
|
||||
|
||||
/* Parse command line arguments */
|
||||
static int parse_command(int argc, char **argv, shine_config_t *config) {
|
||||
int i = 0;
|
||||
|
||||
if (argc < 3) return 0;
|
||||
|
||||
while (argv[++i][0] == '-' && argv[i][1] != '\000' && argv[i][1] != ' ')
|
||||
switch (argv[i][1]) {
|
||||
case 'b':
|
||||
config->mpeg.bitr = atoi(argv[++i]);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
force_mono = 1;
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
stereo = JOINT_STEREO;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
stereo = DUAL_CHANNEL;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
config->mpeg.copyright = 1;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
quiet = 0;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default :
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc - i != 2) return 0;
|
||||
infname = argv[i++];
|
||||
outfname = argv[i];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print some info about what we're going to encode */
|
||||
static void check_config(shine_config_t *config) {
|
||||
static char *version_names[4] = {"2.5", "reserved", "II", "I"};
|
||||
static char *mode_names[4] = {"stereo", "joint-stereo", "dual-channel", "mono"};
|
||||
static char *demp_names[4] = {"none", "50/15us", "", "CITT"};
|
||||
|
||||
printf("MPEG-%s layer III, %s Psychoacoustic Model: Shine\n",
|
||||
version_names[shine_check_config(config->wave.samplerate, config->mpeg.bitr)],
|
||||
mode_names[config->mpeg.mode]);
|
||||
printf("Bitrate: %d kbps ", config->mpeg.bitr);
|
||||
printf("De-emphasis: %s %s %s\n",
|
||||
demp_names[config->mpeg.emph],
|
||||
((config->mpeg.original) ? "Original" : ""),
|
||||
((config->mpeg.copyright) ? "(C)" : ""));
|
||||
printf("Encoding \"%s\" to \"%s\"\n", infname, outfname);
|
||||
}
|
||||
|
||||
int mainmp3(int argc, wchar_t *wargv[]) {
|
||||
char **argv = new char *[argc];
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
int length = WideCharToMultiByte(CP_ACP, 0, wargv[i], -1, NULL, 0, NULL, NULL);
|
||||
argv[i] = new char[length];
|
||||
WideCharToMultiByte(CP_ACP, 0, wargv[i], -1, argv[i], length, NULL, NULL);
|
||||
}
|
||||
shine_config_t config;
|
||||
shine_t s;
|
||||
int written;
|
||||
unsigned char *data;
|
||||
/* Set the default MPEG encoding paramters - basically init the struct */
|
||||
set_defaults(&config);
|
||||
|
||||
if (!parse_command(argc, argv, &config)) {
|
||||
print_usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
quiet = quiet || !strcmp(outfname, "-");
|
||||
|
||||
if (!quiet) {
|
||||
printf("Audio Processing\n");
|
||||
printf("mp3 encoder && decoder\n");
|
||||
printf("blog:http://cpuimage.cnblogs.com/\n");
|
||||
}
|
||||
uint32_t sampleRate = 0;
|
||||
uint64_t totalSampleCount = 0;
|
||||
uint32_t channels = 0;
|
||||
int16_t *data_in = wavRead_int16(infname, &sampleRate, &channels, &totalSampleCount);
|
||||
if (data_in == NULL)
|
||||
return -1;
|
||||
double startTime = now();
|
||||
config.wave.samplerate = sampleRate;
|
||||
config.wave.channels = (decltype(config.wave.channels))channels;
|
||||
|
||||
if (force_mono)
|
||||
config.wave.channels = (decltype(config.wave.channels))1;
|
||||
|
||||
/* See if samplerate and bitrate are valid */
|
||||
if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0)
|
||||
error("Unsupported samplerate/bitrate configuration.");
|
||||
|
||||
/* open the output file */
|
||||
if (!strcmp(outfname, "-"))
|
||||
outfile = stdout;
|
||||
else
|
||||
outfile = fopen(outfname, "wb");
|
||||
if (!outfile) {
|
||||
fprintf(stderr, "Could not create \"%s\".\n", outfname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Set to stereo mode if wave data is stereo, mono otherwise. */
|
||||
if (config.wave.channels > 1)
|
||||
config.mpeg.mode = (decltype(config.mpeg.mode))stereo;
|
||||
else
|
||||
config.mpeg.mode = MONO;
|
||||
|
||||
/* Initiate encoder */
|
||||
s = shine_initialise(&config);
|
||||
|
||||
// assert(s != NULL);
|
||||
/* Print some info about the file about to be created (optional) */
|
||||
if (!quiet) check_config(&config);
|
||||
|
||||
int samples_per_pass = shine_samples_per_pass(s) * channels;
|
||||
|
||||
/* All the magic happens here */
|
||||
size_t count = totalSampleCount / samples_per_pass;
|
||||
int16_t *buffer = data_in;
|
||||
for (int i = 0; i < count; i++) {
|
||||
data = shine_encode_buffer_interleaved(s, buffer, &written);
|
||||
if (write_mp3(written, data, &config) != written) {
|
||||
fprintf(stderr, "mp3 encoder && decoder: write error\n");
|
||||
return 1;
|
||||
}
|
||||
buffer += samples_per_pass;
|
||||
}
|
||||
size_t last = totalSampleCount % samples_per_pass;
|
||||
if (last != 0) {
|
||||
int16_t *cache = (int16_t *) calloc(samples_per_pass, sizeof(int16_t));
|
||||
if (cache != NULL) {
|
||||
memcpy(cache, buffer, last * sizeof(int16_t));
|
||||
data = shine_encode_buffer_interleaved(s, cache, &written);
|
||||
free(cache);
|
||||
if (write_mp3(written, data, &config) != written) {
|
||||
fprintf(stderr, "mp3 encoder && decoder: write error\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Flush and write remaining data. */
|
||||
data = shine_flush(s, &written);
|
||||
write_mp3(written, data, &config);
|
||||
/* Close encoder. */
|
||||
shine_close(s);
|
||||
/* Close the MP3 file */
|
||||
fclose(outfile);
|
||||
free(data_in);
|
||||
double time_interval = calcElapsed(startTime, now());
|
||||
if (!quiet)
|
||||
printf("time interval: %d ms\n ", (int) (time_interval * 1000));
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
#pragma comment(linker, "/subsystem:windows /entry:wmainCRTStartup")
|
||||
int recordaudio(int argc, wchar_t *argv[]);
|
||||
|
||||
int dllinjectwmain(int argc, wchar_t *argv[]);
|
||||
int ntleaswmain(int argc, wchar_t *wargv[]);
|
||||
int updatewmain(int argc, wchar_t *wargv[]);
|
||||
bool checkisapatch();
|
||||
#ifndef _WIN64
|
||||
int recordaudio(int argc, wchar_t *argv[]);
|
||||
int mainmp3(int argc, wchar_t *argv[]);
|
||||
int LRwmain(int argc, wchar_t *argv[]);
|
||||
int jbjwmain(int argc, wchar_t *argv[]);
|
||||
int dreyewmain(int argc, wchar_t *argv[]);
|
||||
@ -65,9 +66,11 @@ int wmain(int argc, wchar_t *argv[])
|
||||
return listprocessmodule(argc - 1, argv + 1);
|
||||
if (argv0 == L"update")
|
||||
return updatewmain(argc - 1, argv + 1);
|
||||
if (argv0 == L"recordaudio")
|
||||
return recordaudio(argc - 1, argv + 1);
|
||||
#ifndef _WIN64
|
||||
else if (argv0 == L"recordaudio")
|
||||
return recordaudio(argc - 1, argv + 1);
|
||||
else if (argv0 == L"mainmp3")
|
||||
return mainmp3(argc - 1, argv + 1);
|
||||
else if (argv0 == L"LR")
|
||||
return LRwmain(argc - 1, argv + 1);
|
||||
else if (argv0 == L"le")
|
||||
|
@ -11,7 +11,7 @@ generate_product_version(
|
||||
VERSION_PATCH ${VERSION_PATCH}
|
||||
)
|
||||
|
||||
add_library(winsharedutils MODULE ../implsapi.cpp hwnd.cpp darklistener.cpp theme.cpp version.cpp otsu.cpp cinterface.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp maglistener.cpp ${versioninfo})
|
||||
add_library(winsharedutils MODULE audio.cpp ../implsapi.cpp hwnd.cpp darklistener.cpp theme.cpp version.cpp otsu.cpp cinterface.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp maglistener.cpp ${versioninfo})
|
||||
target_precompile_headers(winsharedutils REUSE_FROM pch)
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||
set_target_properties(winsharedutils PROPERTIES OUTPUT_NAME "winsharedutils64")
|
||||
|
71
plugins/winsharedutils/audio.cpp
Normal file
71
plugins/winsharedutils/audio.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include <miniaudio.h>
|
||||
|
||||
void data_callback(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount)
|
||||
{
|
||||
ma_decoder *pDecoder = (ma_decoder *)pDevice->pUserData;
|
||||
if (pDecoder == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount, NULL);
|
||||
|
||||
(void)pInput;
|
||||
}
|
||||
extern "C" __declspec(dllexport) void PlayAudioInMem_Stop(ma_decoder *decoder, ma_device *device)
|
||||
{
|
||||
ma_device_stop(device);
|
||||
ma_device_uninit(device);
|
||||
ma_decoder_uninit(decoder);
|
||||
delete decoder;
|
||||
delete device;
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) int PlayAudioInMem(void *ptr, size_t len, float volume, ma_decoder **decoderet, ma_device **deviceret, float *duration)
|
||||
{
|
||||
ma_result result;
|
||||
ma_decoder *decoder = new ma_decoder;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device *device = new ma_device;
|
||||
ZeroMemory(device, sizeof(ma_device));
|
||||
ZeroMemory(decoder, sizeof(ma_decoder));
|
||||
result = ma_decoder_init_memory(ptr, len, NULL, decoder);
|
||||
if (result != MA_SUCCESS)
|
||||
{
|
||||
delete decoder;
|
||||
delete device;
|
||||
return -2;
|
||||
}
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
deviceConfig.playback.format = decoder->outputFormat;
|
||||
deviceConfig.playback.channels = decoder->outputChannels;
|
||||
deviceConfig.sampleRate = decoder->outputSampleRate;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = decoder;
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, device) != MA_SUCCESS)
|
||||
{
|
||||
ma_decoder_uninit(decoder);
|
||||
delete decoder;
|
||||
delete device;
|
||||
return -3;
|
||||
}
|
||||
ma_device_set_master_volume(device, volume);
|
||||
if (ma_device_start(device) != MA_SUCCESS)
|
||||
{
|
||||
ma_device_uninit(device);
|
||||
ma_decoder_uninit(decoder);
|
||||
delete decoder;
|
||||
delete device;
|
||||
return -4;
|
||||
}
|
||||
|
||||
*decoderet = decoder;
|
||||
*deviceret = device;
|
||||
ma_uint64 frames;
|
||||
ma_decoder_get_length_in_pcm_frames(decoder, &frames);
|
||||
*duration = 1.0f * frames / (decoder->outputSampleRate);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user