- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我以libmad示例C文件为例,并播放了一个mp3,效果很好。但是,当我尝试分块读取文件时,而不是一次读取文件的示例,我听到“中断”的声音,并且播放速度太快了。
这是我的输入回调和我的输出回调
static enum mad_flow input(void *data, struct mad_stream *stream) {
struct buffer *buffer = data;
// char* raw_data[buffer->size];
// if(fgets(*raw_data, buffer->size, buffer->file) == NULL) {
// file is finished!
// in our case we would want to move to next file here!
// when we get there, we will get data from node->file of LL, instead of file.
// with node->file, we can simply move to next song when playing the music.
// return MAD_FLOW_STOP;
// }
//printf("%s\n",*raw_data);
void *fdm;
fdm = mmap(0, BUFFER_SIZE, PROT_READ, MAP_SHARED, buffer->fd, buffer->offset);
if (fdm == MAP_FAILED) {
printf("%s\n","failed");
return MAD_FLOW_STOP;
}
if(buffer->offset >= buffer->size) {
if (munmap(fdm, BUFFER_SIZE) == -1)
return MAD_FLOW_STOP;
return MAD_FLOW_STOP;
}
mad_stream_buffer(stream, fdm, BUFFER_SIZE);
printf("size is %lu and offset is %lu\n",buffer->size, buffer->offset);
buffer->offset += BUFFER_SIZE;
printf("%s\n","read");
return MAD_FLOW_CONTINUE;
}
static enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) {
register int nsamples = pcm->length;
mad_fixed_t const *left_ch = pcm->samples[0], *right_ch = pcm->samples[1];
static unsigned char stream[1152*4]; /* 1152 because that's what mad has as a max; *4 because
there are 4 distinct bytes per sample (in 2 channel case) */
static unsigned int rate = 0;
static int channels = 0;
//static struct audio_dither dither;
register char * ptr = stream;
register signed int sample;
register mad_fixed_t tempsample;
printf("%s\n", "playing");
/* We need to know information about the file before we can open the playdevice
in some cases. So, we do it here. */
if (pcm->channels == 2) {
while (nsamples--) {
signed int sample;
sample = scale(*left_ch++);
// sample = (signed int) audio_linear_dither(16, tempsample, &dither);
stream[(pcm->length-nsamples)*4 ] = ((sample >> 0) & 0xff);
stream[(pcm->length-nsamples)*4 +1] = ((sample >> 8) & 0xff);
sample = scale(*right_ch++);
stream[(pcm->length-nsamples)*4+2 ] = ((sample >> 0) & 0xff);
stream[(pcm->length-nsamples)*4 +3] = ((sample >> 8) & 0xff);
}
ao_play(device, stream, pcm->length * 4);
} else {
while (nsamples--) {
signed int sample;
sample = scale(*left_ch++);
stream[(pcm->length-nsamples)*2 ] = ((sample >> 0) & 0xff);
stream[(pcm->length-nsamples)*2 +1] = ((sample >> 8) & 0xff);
}
ao_play(device, stream, pcm->length * 2);
}
return MAD_FLOW_CONTINUE;
}
https://github.com/fasterthanlime/libmad/blob/master/minimad.c
最佳答案
这是一个古老的问题,但是我遇到了同样的问题,目前充其量很难找到简单的示例代码来做到这一点,甚至很难在邮件列表之外进行详尽的解释。
首先,关于您的特定代码,我不知道每次都只对文件的一小部分调用mmap(),而不是对整个文件进行mmap()调用。 mmap()不会像您想象的那样将文件读入内存。它甚至不为整个文件分配物理内存。它仅分配虚拟内存。每当您的程序从尚未加载的虚拟内存(页面错误处理程序)中读取数据时,操作系统就会负责将文件读取到物理内存中,并且每当有程序再次从物理内存中删除文件的某些部分时其他地方需要物理内存。
话虽如此,如果您使用的是没有内存管理单元的嵌入式系统,则不会有具有这些特征的mmap(),并且您可能也没有足够的物理内存来将整个MP3文件加载到内存中。因此,对于本说明的其余部分,我假设您正在使用一些类似于read()的泛型函数来获取数据,并拥有一个目标系统,其内存大小以千字节为单位。
问题
问题是mad_stream_buffer()不会执行您认为或希望执行的操作。它使您认为它将向内部流添加您提供的任何缓冲区,并在该流运行不足时调用input()。但是没有内部流。 libmad只能使用您提供的缓冲区,调用mad_stream_buffer()只会替换缓冲区指针。
要真正理解这是一个问题的原因,您还需要了解MP3的工作原理。 MP3文件的音频部分分为称为“帧”的数据块。帧是按字节对齐的,并从全部设置为1的比特串开始,称为同步字。在开始播放或搜索后,用于查找第一帧的开始。 libmad将在调用input()回调后始终在其当前输入缓冲区中查找第一个同步字,并跳过找到的第一个同步字之前的任何数据。然后,libmad将开始解码MP3帧,直到没有数据剩余或遇到不完整的帧为止。最后的不完整帧也将被忽略,并再次调用input()。
所以最终发生的事情看起来像这样:
| read() 1 | read() 2 | read() 3 | read() 4 |
|hdr|frame1|??????|frame3|frame4|??????|frame6|??????|frame8|frame9|?
input():
| read() 1 |
|hdr|frame1|frame|
decoded as:
| buffer 1 |
|???|frame1|?????|
|
input(): |
.----------'
v | read() 2 |
|frame2|frame3|fr|
decoded as:
| buffer 2 |
|frame2|frame3|??|
|
input(): |
.-------------'
v | read() 3 |
|frame4|frame5|fr|
decoded as:
| buffer 3 |
|frame4|frame5|??|
error
的输入的
struct mad_stream
参数中设置
MAD_ERROR_BUFLEN
条目。如果它在帧的中间结束,则
next_frame
条目将设置为先前给定数据缓冲区中的指针,该指针标记不完整帧的开始。如果缓冲区中根本没有帧,则此指针的值将为null。在这种情况下,如果有错误回调,您还将在错误回调中收到“同步丢失”错误。
MAD_BUFFER_GUARD
。那将至少是2881个字节长(
source)。但这是假设缓冲区始于帧的开始。如果您不知道第一帧的位置(即MP3文件的开头),则需要在这种情况下逐字节移动数据缓冲区,以在最坏的情况下找到它。因此,您最好将电源关闭两次。
error
不是MAD_ERROR_BUFLEN
,则使用全新的数据块加载数据缓冲区并返回。 next_frame
,则将(上一个)缓冲区的未使用部分移至缓冲区的开头,然后用新数据填充缓冲区的其余部分。 next_frame
为null,则尚未找到有效的帧。为了确保不跳过第一帧(可能已经部分缓存在其中),我们需要将数据缓存最多移位(buflen-max_frame_size),并用新数据填充缓存的其余部分。 MAD_BUFFER_GUARD
零字节。 #define MP3_BUF_SIZE 4096
#define MP3_FRAME_SIZE 2881
static enum mad_flow input(void *data, struct mad_stream *stream) {
static char mp3_buf[MP3_BUF_SIZE]; /* MP3 data buffer. */
int keep; /* Number of bytes to keep from the previous buffer. */
int retval; /* Return value from read(). */
int len; /* Length of the new buffer. */
int eof; /* Whether this is the last buffer that we can provide. */
/* Figure out how much data we need to move from the end of the previous
buffer into the start of the new buffer. */
if (stream->error != MAD_ERROR_BUFLEN) {
/* All data has been consumed, or this is the first call. */
keep = 0;
} else if (stream->next_frame != NULL) {
/* The previous buffer was consumed partially. Move the unconsumed portion
into the new buffer. */
keep = stream->bufend - stream->next_frame;
} else if ((stream->bufend - stream->buffer) < MP3_BUF_SIZE) {
/* No data has been consumed at all, but our read buffer isn't full yet,
so let's just read more data first. */
keep = stream->bufend - stream->buffer;
} else {
/* No data has been consumed at all, and our read buffer is already full.
Shift the buffer to make room for more data, in such a way that any
possible frame position in the file is completely in the buffer at least
once. */
keep = MP3_BUF_SIZE - MP3_FRAME_SIZE;
}
/* Shift the end of the previous buffer to the start of the new buffer if we
want to keep any bytes. */
if (keep) {
memmove(mp3_buf, stream->bufend - keep, keep);
}
/* Append new data to the buffer. */
retval = read(in_fd, mp3_buf + keep, MP3_BUF_SIZE - keep);
if (retval < 0) {
/* Read error. */
perror("failed to read from input");
return MAD_FLOW_STOP;
} else if (retval == 0) {
/* End of file. Append MAD_BUFFER_GUARD zero bytes to make sure that the
last frame is properly decoded. */
if (keep + MAD_BUFFER_GUARD <= MP3_BUF_SIZE) {
/* Append all guard bytes and stop decoding after this buffer. */
memset(mp3_buf + keep, 0, MAD_BUFFER_GUARD);
len = keep + MAD_BUFFER_GUARD;
eof = 1;
} else {
/* The guard bytes don't all fit in our buffer, so we need to continue
decoding and write all fo teh guard bytes in the next call to input(). */
memset(mp3_buf + keep, 0, MP3_BUF_SIZE - keep);
len = MP3_BUF_SIZE;
eof = 0;
}
} else {
/* New buffer length is amount of bytes that we kept from the previous
buffer plus the bytes that we read just now. */
len = keep + retval;
eof = 0;
}
/* Pass the new buffer information to libmad. */
mad_stream_buffer(stream, mp3_buf, len);
return eof ? MAD_FLOW_STOP : MAD_FLOW_CONTINUE;
}
关于c - 如果分块读取,libmad播放速度太快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39803572/
我在想出一个算法时遇到了麻烦... 我有一系列 GPS 数据,以 1 秒为间隔记录时间、速度、距离。假设距离是米,速度是米/秒。可能有超过 2 小时的数据,或 7200 个点。这里的“时间”字段主要是
使用java排序器,即: Collections.sort(myArrayList, new Comparator() { @Override public int c
有什么区别吗 SELECT * FROM my_table 和 SELECT my_column_id FROM my_table 地点: my_table 有百万行 网站上有大量并发用户进行sql查
有2个样本。 在第一个示例中,使用 orderby 可以更快地获得结果。 (根据 phpmyadmin 速度报告) 在另一个例子中,我没有使用 order by,它给出的结果较慢。 (根据 phpmy
我注意到,如果我将训练数据加载到内存中并将其作为 numpy 数组提供到图中,与使用相同大小的 shuffle 批次相比,速度会有很大差异,我的数据有大约 1000 个实例。 使用内存 1000 次迭
我在 python 中使用破折号。我正在绘制记录到 SQLite 数据库中的实时数据,目前,我正在绘制单个值与时间线图。我计划再添加 20 个图表,但目前,随着时间的增加, plotly 变慢,我认为
我试图调用 hasNext Velocity 模板中的方法,以便根据 foreach 循环中的位置影响行为 - 仅 hasNext没有按照文档工作。 这是 Velocity 用户指南的片段,关于 ha
在我正在制作的游戏中,我有两个点,pt1 和 pt2,我想计算出它们之间的角度。我已经在较早的计算中计算出距离。显而易见的方法是对垂直距离上的水平距离进行反正切 (tan(theta) = opp/a
我经常遇到字符串值不存在和/或为空的情况。这是测试这种情况的最佳方法吗? #if( $incentive.disclaimer && $!incentive.disclaimer != '' )
我想将一个模板nested包含在其他模板cont1,cont2和cont3中。 并且嵌套模板应仅对cont1隐藏一个特定控件。 在包含在cont1中之前,我想为一些标志变量$hideMyControl
是否可以更改从“Windows Azure Media Encoder”输出的音频的播放速度? 我正在使用配置为“WMA High Quality Audio”的“Windows Azure Medi
我使用速度将String(template)与字段合并 hi there I'am ${name}, And I'am ${age} old. velocity将字段${name}和${age}与一种
我使用的是 LockedBitmap 类,它简化了 C# 中位图数据的处理。目前它正在将数据复制到本地 byte[] 数组中,然后通过其类方法访问该数组以获取/设置像素颜色值。 这比直接通过指针访问锁
我尝试在 VM_global_library.vm 文件中添加一堆 #set($x=abc) 语句,但这些变量在我的 VM 模板中不可用。 我想为图像的基本路径等设置一个全局变量。这可能吗? 最佳答案
我的项目结构: -src --main ---java ----makers -----SomeClass ---resources ----htmlPattern.vm 如何告诉 SomeClass
我正在尝试从 Velocity 中的字符串中删除不需要的字符(换行符可以,但不能像 EM 和 CAN ASCII 控制字符那样)。 #set($cleanScreen = $cleanScreen.r
我想在日.月.年之间的点处分割日期。例如:2015 年 1 月 14 日至 {14, 01, 2015}这是我使用的代码:dates3.get(0) 包含我从页面的文本字段获取的字符串“14.01.2
之后,从 1.5 升级到速度引擎 1.7 出现了 1.5 没有的问题。为了解释这个问题,我必须展示一个代码片段: #foreach($someVariable in $someCollection)
我想知道从表中选择所有字段是否更快: SELECT * 或只选择您真正需要的: SELECT field1, field2, field3, field4, field5... 假设表有大约 10 个
我正在尝试模仿照片应用程序的行为,在该应用程序中,用户用手指平移照片并且照片具有一定的速度。由于我不会深入的原因,我不能将 UIScrollView 与它的缩放 UIImageView 一起使用,而是
我是一名优秀的程序员,十分优秀!