最近有个粉丝想要藏语的tts,不清楚他是开发还是想怎么实现,于是
从py移植了一个藏语模型
我叫他哈达TTS
启动程序

然后用postman测试

返回语音流,或者返回base64 json 也行
非py开发,所以不依赖py环境
方法就是把tts模型转成onnx,然后用c++调用
但我是delphi,就又转了一层
unit U_MmsTokenizer;
interface
uses
System.SysUtils, System.Classes, System.Generics.Collections,System.IOUtils;
type
TMmsTokenized = record
InputIds: TArray<Int64>;
AttentionMask: TArray<Int64>;
end;
TMmsTokenizer = class
private
FVocab: TDictionary<string, Integer>;
FUnkId: Integer;
FBlankId: Integer;
FPadId: Integer;
FAddBlank: Boolean;
function TokenToId(const Tok: string): Integer;
function NormalizeText(const S: string): string;
public
constructor Create;
destructor Destroy; override;
procedure LoadFromFiles(const VocabFile, TokenizerConfigFile: string);
function Encode(const Text: string; MinSeqLen: Integer = 24): TMmsTokenized;
end;
implementation
uses
System.JSON;
constructor TMmsTokenizer.Create;
begin
inherited Create;
FVocab := TDictionary<string, Integer>.Create;
FUnkId := 0;
FBlankId := 1;
FPadId := 1;
FAddBlank := True;
end;
destructor TMmsTokenizer.Destroy;
begin
FVocab.Free;
inherited;
end;
function TMmsTokenizer.NormalizeText(const S: string): string;
begin
Result := Trim(S);
Result := StringReplace(Result, #13, ' ', [rfReplaceAll]);
Result := StringReplace(Result, #10, ' ', [rfReplaceAll]);
Result := StringReplace(Result, #9, ' ', [rfReplaceAll]);
end;
function TMmsTokenizer.TokenToId(const Tok: string): Integer;
begin
if not FVocab.TryGetValue(Tok, Result) then
Result := FUnkId;
end;
procedure TMmsTokenizer.LoadFromFiles(const VocabFile, TokenizerConfigFile: string);
var
S: string;
J, Cfg: TJSONObject;
P: TJSONPair;
V: Integer;
AddBlankV: TJSONValue;
begin
FVocab.Clear;
S := TFile.ReadAllText(VocabFile, TEncoding.UTF8);
J := TJSONObject.ParseJSONValue(S) as TJSONObject;
if J = nil then
raise Exception.Create('Invalid vocab.json');
try
for P in J do
begin
V := StrToIntDef(P.JsonValue.Value, -1);
if V >= 0 then
FVocab.AddOrSetValue(P.JsonString.Value, V);
end;
finally
J.Free;
end;
if FVocab.TryGetValue('<unk>', V) then
FUnkId := V
else
FUnkId := 0;
if FVocab.TryGetValue('_', V) then
begin
FBlankId := V;
FPadId := V;
end;
if FileExists(TokenizerConfigFile) then
begin
S := TFile.ReadAllText(TokenizerConfigFile, TEncoding.UTF8);
Cfg := TJSONObject.ParseJSONValue(S) as TJSONObject;
if Cfg <> nil then
try
AddBlankV := Cfg.GetValue('add_blank');
if AddBlankV <> nil then
FAddBlank := SameText(AddBlankV.Value, 'true');
finally
Cfg.Free;
end;
end;
end;
function TMmsTokenizer.Encode(const Text: string; MinSeqLen: Integer): TMmsTokenized;
var
T: string;
Ch: Char;
Tmp: TList<Int64>;
I: Integer;
begin
T := NormalizeText(Text);
if T = '' then
raise Exception.Create('text is required');
Tmp := TList<Int64>.Create;
try
if FAddBlank then
Tmp.Add(FBlankId);
for Ch in T do
begin
Tmp.Add(TokenToId(string(Ch)));
if FAddBlank then
Tmp.Add(FBlankId);
end;
if MinSeqLen < 8 then
MinSeqLen := 8;
while Tmp.Count < MinSeqLen do
begin
Tmp.Add(FPadId);
if FAddBlank and (Tmp.Count < MinSeqLen) then
Tmp.Add(FBlankId);
end;
if Tmp.Count > MinSeqLen then
while Tmp.Count > MinSeqLen do
Tmp.Delete(Tmp.Count - 1);
SetLength(Result.InputIds, Tmp.Count);
SetLength(Result.AttentionMask, Tmp.Count);
for I := 0 to Tmp.Count - 1 do
begin
Result.InputIds[I] := Tmp[I];
Result.AttentionMask[I] := 1;
end;
finally
Tmp.Free;
end;
end;
end.
下载地址
通过网盘分享的文件:HadaTTS.zip
链接: https://pan.baidu.com/s/1x_aZd0RBfOAML0X8Qlwaxw 提取码: ew76