|
|
@ -1,6 +1,7 @@ |
|
|
import 'dart:typed_data'; |
|
|
import 'dart:typed_data'; |
|
|
import 'package:flutter/material.dart'; |
|
|
import 'package:flutter/material.dart'; |
|
|
import 'package:opus/opus.dart'; |
|
|
|
|
|
|
|
|
import '../../lib/opus.dart'; |
|
|
|
|
|
|
|
|
void main() { |
|
|
void main() { |
|
|
runApp(const OpusExampleApp()); |
|
|
runApp(const OpusExampleApp()); |
|
|
@ -92,13 +93,13 @@ class _OpusExamplePageState extends State<OpusExamplePage> { |
|
|
const int frequency = 440; // 440Hz - A4音符 |
|
|
const int frequency = 440; // 440Hz - A4音符 |
|
|
const int durationMs = 20; // 20ms,按照常规frameSize=960 |
|
|
const int durationMs = 20; // 20ms,按照常规frameSize=960 |
|
|
const int frameSize = 960; // 对应20ms@48kHz |
|
|
const int frameSize = 960; // 对应20ms@48kHz |
|
|
|
|
|
|
|
|
// 创建PCM数据缓冲区,16位有符号整数,每采样2字节,双声道 |
|
|
// 创建PCM数据缓冲区,16位有符号整数,每采样2字节,双声道 |
|
|
final int samplesToGenerate = (sampleRate * durationMs / 1000).round(); |
|
|
final int samplesToGenerate = (sampleRate * durationMs / 1000).round(); |
|
|
final int bufferSize = samplesToGenerate * channels * 2; // 2字节/样本 |
|
|
final int bufferSize = samplesToGenerate * channels * 2; // 2字节/样本 |
|
|
|
|
|
|
|
|
final byteBuffer = ByteData(bufferSize); |
|
|
final byteBuffer = ByteData(bufferSize); |
|
|
|
|
|
|
|
|
// 生成正弦波 |
|
|
// 生成正弦波 |
|
|
for (int i = 0; i < samplesToGenerate; i++) { |
|
|
for (int i = 0; i < samplesToGenerate; i++) { |
|
|
// 计算当前时间点 |
|
|
// 计算当前时间点 |
|
|
@ -107,18 +108,17 @@ class _OpusExamplePageState extends State<OpusExamplePage> { |
|
|
final double amplitude = sin(2 * 3.14159265359 * frequency * t); |
|
|
final double amplitude = sin(2 * 3.14159265359 * frequency * t); |
|
|
// 缩放到16位有符号整数范围 (-32768 to 32767) |
|
|
// 缩放到16位有符号整数范围 (-32768 to 32767) |
|
|
final int sample = (amplitude * 32767).round(); |
|
|
final int sample = (amplitude * 32767).round(); |
|
|
|
|
|
|
|
|
// 为所有声道写入相同的值 |
|
|
// 为所有声道写入相同的值 |
|
|
for (int channel = 0; channel < channels; channel++) { |
|
|
for (int channel = 0; channel < channels; channel++) { |
|
|
final int offset = (i * channels + channel) * 2; |
|
|
final int offset = (i * channels + channel) * 2; |
|
|
byteBuffer.setInt16(offset, sample, Endian.little); |
|
|
byteBuffer.setInt16(offset, sample, Endian.little); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_samplePcmData = Uint8List.fromList( |
|
|
_samplePcmData = Uint8List.fromList( |
|
|
List.generate(bufferSize, (index) => byteBuffer.getUint8(index)) |
|
|
List.generate(bufferSize, (index) => byteBuffer.getUint8(index))); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
setState(() { |
|
|
setState(() { |
|
|
_statusMessage = '已创建${_samplePcmData!.length}字节测试PCM数据'; |
|
|
_statusMessage = '已创建${_samplePcmData!.length}字节测试PCM数据'; |
|
|
}); |
|
|
}); |
|
|
@ -272,6 +272,9 @@ class _OpusExamplePageState extends State<OpusExamplePage> { |
|
|
|
|
|
|
|
|
String _formatBytes(Uint8List data) { |
|
|
String _formatBytes(Uint8List data) { |
|
|
final length = data.length > 16 ? 16 : data.length; |
|
|
final length = data.length > 16 ? 16 : data.length; |
|
|
return data.sublist(0, length).map((e) => e.toRadixString(16).padLeft(2, '0')).join(' '); |
|
|
return data |
|
|
|
|
|
.sublist(0, length) |
|
|
|
|
|
.map((e) => e.toRadixString(16).padLeft(2, '0')) |
|
|
|
|
|
.join(' '); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|