feat: Integrate Kokoro TTS with WebGPU and fallback
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
class LinkedList {
|
||||
constructor() {
|
||||
this.head = null;
|
||||
this.tail = null;
|
||||
this.listSize = 0;
|
||||
}
|
||||
|
||||
get size() {
|
||||
return this.listSize;
|
||||
}
|
||||
|
||||
isLinked(node) {
|
||||
return !((node && node.prev === null && node.next === null && this.tail !== node && this.head !== node) || this.isEmpty());
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return this.listSize === 0;
|
||||
}
|
||||
|
||||
get first() {
|
||||
return this.head;
|
||||
}
|
||||
|
||||
get last() {
|
||||
return this.last;
|
||||
}
|
||||
|
||||
|
||||
toString() {
|
||||
return this.toArray().toString();
|
||||
}
|
||||
|
||||
toArray() {
|
||||
var node = this.head,
|
||||
result = [];
|
||||
while (node !== null) {
|
||||
result.push(node);
|
||||
node = node.next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Note that modifying the list during
|
||||
// iteration is not safe.
|
||||
forEach(fun) {
|
||||
var node = this.head;
|
||||
while (node !== null) {
|
||||
fun(node);
|
||||
node = node.next;
|
||||
}
|
||||
}
|
||||
|
||||
contains(n) {
|
||||
var node = this.head;
|
||||
if (!this.isLinked(n)) {
|
||||
return false;
|
||||
}
|
||||
while (node !== null) {
|
||||
if (node === n) {
|
||||
return true;
|
||||
}
|
||||
node = node.next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
at(i) {
|
||||
var node = this.head, index = 0;
|
||||
|
||||
if (i >= this.listLength || i < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while (node !== null) {
|
||||
if (i === index) {
|
||||
return node;
|
||||
}
|
||||
node = node.next;
|
||||
index += 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
insertAfter(node, newNode) {
|
||||
if (!this.isLinked(node)) {
|
||||
return this;
|
||||
}
|
||||
newNode.prev = node;
|
||||
newNode.next = node.next;
|
||||
if (node.next === null) {
|
||||
this.tail = newNode;
|
||||
} else {
|
||||
node.next.prev = newNode;
|
||||
}
|
||||
node.next = newNode;
|
||||
this.listSize += 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
insertBefore(node, newNode) {
|
||||
if (!this.isLinked(node)) {
|
||||
return this;
|
||||
}
|
||||
newNode.prev = node.prev;
|
||||
newNode.next = node;
|
||||
if (node.prev === null) {
|
||||
this.head = newNode;
|
||||
} else {
|
||||
node.prev.next = newNode;
|
||||
}
|
||||
node.prev = newNode;
|
||||
this.listSize += 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
push(node) {
|
||||
if (this.head === null) {
|
||||
this.unshift(node);
|
||||
} else {
|
||||
this.insertAfter(this.tail, node);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
unshift(node) {
|
||||
if (this.head === null) {
|
||||
this.head = node;
|
||||
this.tail = node;
|
||||
node.prev = null;
|
||||
node.next = null;
|
||||
this.listSize += 1;
|
||||
} else {
|
||||
this.insertBefore(this.head, node);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
remove(node) {
|
||||
if (!this.isLinked(node)) {
|
||||
return this;
|
||||
}
|
||||
if (node.prev === null) {
|
||||
this.head = node.next;
|
||||
} else {
|
||||
node.prev.next = node.next;
|
||||
}
|
||||
if (node.next === null) {
|
||||
this.tail = node.prev;
|
||||
} else {
|
||||
node.next.prev = node.prev;
|
||||
}
|
||||
this.listSize -= 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
pop() {
|
||||
var node = this.tail;
|
||||
this.tail.prev.next = null;
|
||||
this.tail = this.tail.prev;
|
||||
this.listSize -= 1;
|
||||
node.prev = null;
|
||||
node.next = null;
|
||||
return node;
|
||||
}
|
||||
|
||||
shift() {
|
||||
var node = this.head;
|
||||
this.head.next.prev = null;
|
||||
this.head = this.head.next;
|
||||
this.listSize -= 1;
|
||||
node.prev = null;
|
||||
node.next = null;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
class Node {
|
||||
constructor(data) {
|
||||
this.prev = null;
|
||||
this.next = null;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.data.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user