描画音效波形

liujiaji 2010-01-18 05:00:52
写了n个有关这个帖子,还没解决啊!杯具了。

求gamedragon和csdner帮忙

x轴的时间和y轴的点式如何确定的。

这是csdner代码确定y点的:DrawValue = CalDrawValue(nVar, p->Format.wBitsPerSample, buf);
buf += n;//n是音频数据中移动的位数。
在往后:nYValue = (int)((double)DrawValue * dbYUnit + 0.5);//这是什么意思?
确定x点的:用到了一个这个变量:m_nCapSamples,这是什么,怎么来的?


gamedragon:看看这段代码:
for(int register x=0;x<(long)size;x=x+n) //to draw first channel
{
sample=pWnd->m_pfch->wBitsPerSample ==8?( (*((BYTE*)pWnd->m_data+x)-128)*h)/128:((*((short*)pWnd->m_data+x))*h)/(65535/2);
pWnd->m_MDC.LineTo (int(((float)x/size)*(pWnd->memrec.Width()-b)),yy-sample);
}
x是音频数据中移动的位置。

谢谢!
...全文
175 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
HUAXIANGDAGE 2010-01-19
  • 打赏
  • 举报
回复
牟得法,顶!!!!!!!!!!
liujiaji 2010-01-19
  • 打赏
  • 举报
回复
我的思想也是不断向描画函数传递音频数据(也就是waveoutwrite里的那个数据),但是就是不清楚x轴和y轴的关系,及sample怎么确定。你看我的那个sample这么求对不对?
我也参考了其它的:也有这么求的:
sample=pWnd->m_pfch->wBitsPerSample ==8?( (*((BYTE*)pWnd->m_data+x)-128)*h)/128:((*((short*)pWnd->m_data+x))*h)/(65535/2);
红色部分就是得到buffer中的值,并且是跳跃的去取(x是变化的,是不断加跳跃值)
liujiaji 2010-01-19
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 traceless 的回复:]
LZ你的结构体定的太大了,装的东西太多,虽然这不是重点。但不好

播放时间? 你指的是总的播放时间,还是当前播放了的时间?有时跳出代码来想问题,更清晰。要不然你回头
再回忆这种问题时候,真的感觉就像白痴,呵呵

在播放的时候,不断像画图函数传数据,就变成了动态了。
[/Quote]
我指的是播放总时间,这个我能得到,在代码中:
//get the time of the audio
time = GetAudioTime(Reader);
能得到一共多少秒,我还是不清楚那个sample为什么那么计算,是原理还是公式?
怎么能刷屏呢?多有打扰。
traceless 2010-01-19
  • 打赏
  • 举报
回复
不断向
traceless 2010-01-19
  • 打赏
  • 举报
回复
LZ你的结构体定的太大了,装的东西太多,虽然这不是重点。但不好

播放时间? 你指的是总的播放时间,还是当前播放了的时间?有时跳出代码来想问题,更清晰。要不然你回头
再回忆这种问题时候,真的感觉就像白痴,呵呵

在播放的时候,不断像画图函数传数据,就变成了动态了。
liujiaji 2010-01-19
  • 打赏
  • 举报
回复
我感觉除了那几个问题还有:
1.是不是播放时间应该是静态变量,假如第二次传音频数据的时候,时间应该是不是总时间减去上一次耗去的时间?
2.如何能刷屏幕呢?就感觉波形是向前走。

liujiaji 2010-01-19
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 traceless 的回复:]
自定义的结构体是不?
[/Quote]
To Csdner(traceless):不好意思,晚些就回家了!
waveout子自定义的结构体,能够得到音频的一些属性,比如:采样率,比特率,通道等,并且在计算中还可以取得音频的大小和播放时间。
liujiaji 2010-01-19
  • 打赏
  • 举报
回复
波形描画的差不多了,特别感谢csdner和gamedragon

这一贴先结了,等我整差不多了,另开贴散专业技术分给你俩!
liujiaji 2010-01-19
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 huaxiangdage 的回复:]
牟得法,顶!!!!!!!!!!
[/Quote]
顶贴的谢谢奥!
traceless 2010-01-18
  • 打赏
  • 举报
回复
自定义的结构体是不?
traceless 2010-01-18
  • 打赏
  • 举报
回复
To liujiaji:

上面代码的waveout是你自动一定的结构体是不?
newman1985 2010-01-18
  • 打赏
  • 举报
回复
可以试试根据音频数据的pcm数据算出来显示
liujiaji 2010-01-18
  • 打赏
  • 举报
回复
不是频谱,比频谱简单多的波形显示。要是频谱更难了。
liujiaji 2010-01-18
  • 打赏
  • 举报
回复
是啊,哎,不会啊!
newman1985 2010-01-18
  • 打赏
  • 举报
回复
画频谱的?
liujiaji 2010-01-18
  • 打赏
  • 举报
回复
To Csdner(traceless):
以下是代码:
1.播放音频及打开音效可视化相关代码:(在播放线程里面,也是在一个死循环调用)
if (waveOutWrite(p->Handle, &Buffer->Head, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
{
ReleaseBuffer(p,Buffer,0);
}
else
{
InterlockedIncrement(&p->Waiting);
}
if(VisualOpen == TRUE)//当打开波形显示效果

{
if( p->effect_run )
{
p->effect_run(p,Buffer->Head.lpData,Buffer->Head.dwBufferLength);//调用可视化回调
//函数
}
//以上的想法是:当打开可视化效果开关的时候,这次有多少数据向音频设备输入,就将这些数据做为波形显
//示的基本数据。其中Buffer->Head.lpData是指向音频数据指针。dwBufferLength是这次数据的空间大小。


2.回调函数:p->effect_run = EffectRun;
static void EffectRun(waveout *p,char* lpData,int length)
{
if(p->Wnd == NULL)
{
p->Wnd = Context()->Wnd;
if ( !IsWindowVisible(p->Wnd) )
{
return ERR_NONE;
}
}
p->m_MDC = GetDC(p->Wnd);
DrawRun(p,lpData,length);//调用可视化效果函数
}

3.画波形显示函数
static void DrawRun(waveout *p,char * lpData,int length)
{
double span,dbYUnit;
int DrawValue;
int pps,yy,b,h,n;
char *bufL,*bufR;
int register x;
int time;
short sample;
node* Reader = NULL;
HPEN hPen, oldp;
RECT rect;
HDC hDC;
long size;
DWORD TrueSize;
int nVar;
HWND Wnd = Context()->Wnd;
node* Player = Context()->Player;
hDC = p->m_MDC;

hPen = CreatePen( PS_SOLID,0,RGB(0,255,0) );
oldp = SelectObject( p->m_MDC, hPen );

//get the size of the audio
Player->Get(Player,PLAYER_FORMAT,&Reader,sizeof(Reader));
size = (GetAudioSize(Reader)) * 1000;
//get the audio visual size
TrueSize = p->Format.wBitsPerSample == 16 ? size/2 : size;
//get the time of the audio
time = GetAudioTime(Reader);
//if the time<10 calculate the wave width
b = time < 10 ? (400-(400/10)*time):0;//这里的400是我假设的屏幕宽度
//get how many pixles per scond
pps = (400)*15 / time;
//get the number of escapes
n = p->Format.nSamplesPerSec / pps;
//get the y of the first channel
yy = 400 / 4;
// move to the orgin
MoveToEx(p->m_MDC,0,400,NULL);
//get the hight of the first channel
h = yy;
///////////////////////////////
span = (double)((1 << p->Format.wBitsPerSample) - 1);//这是你的代码应用
dbYUnit = (double)((double)400 / span);//这是你的代码应用
/*取得有符号整型数的最大值*/
nVar = (p->Format.wBitsPerSample == 8? 255 : (p->Format.wBitsPerSample == 16? (1<<15)-1 : (p->Format.wBitsPerSample == 32? (unsigned int)(1<<31)-1 : (1<<15)+(1<<7)-1) ));
/*以下是这么想的,将传过来的音频数据复制到一个buuffer中.*/
bufL = (char*)malloc(sizeof(char)*length);
if(!bufL)
{
return ERR_OUT_OF_MEMORY;
}
memset(bufL,'\0',sizeof(char)*length);
memcpy(bufL,lpData,length);//将从waveOutWrite中那个音频数据复制到bufL中。
///////////////////////////////
//to draw first channel
for(x=0;x<length;x=x+n)//lenght是存放数据的空间大小,n是跳跃值。这里我不清楚,为什么不能连
//续读里面的数据。而要跳跃的去取里面的音频数据
{
DrawValue = CalDrawValue(nVar, p->Format.wBitsPerSample, bufL+x);//这是你的代码
sample = (int)((double)DrawValue * dbYUnit + 0.5);//这么计算不知道为什么?
LineTo(p->m_MDC,(int)(((float)x/TrueSize)*(400 - b)),yy -
sample);//LineTo里的横坐标是时间,现在不知道如何计算,x坐标瞎写的。
}
if(!bufL)
free(bufL);
bufL = NULL;

/*这是计算第二个声道*/

bufR = (char*)malloc(sizeof(char)*length);
if(!bufR)
{
return ERR_OUT_OF_MEMORY;
}
memset(bufR,'\0',sizeof(char)*length);
memcpy(bufR,lpData,length);

yy = yy + h + h/2;
MoveToEx(p->m_MDC,0,yy,NULL);
// go here if the wave is stereo
if(p->Format.nChannels > 1)
{ // to draw the scond channel
for(x=1;x<length;x=x+n)
{
DrawValue = CalDrawValue(nVar, p->Format.wBitsPerSample, bufR+x);
sample = (int)((double)DrawValue * dbYUnit + 0.5);
LineTo(p->m_MDC,(int)(((float)x/TrueSize)*(400 - b)),yy - sample);
}
}
if(bufR != NULL)
free(bufR);
bufR = NULL;
}
/*
*目前只要能显示一屏就行。
*主要不清楚采样点sample:是根据什么得到的。有固定的公式吗?
*横坐标是时间,时间如何计算。
*时间到像素有什么对应关系。
*/

//////////////////////////////////////////////////////////////////////////////////////////////
可惜不能按你的要求能贴上可以运行的代码。

谢谢!

liujiaji 2010-01-18
  • 打赏
  • 举报
回复
好的。谢谢!你先忙你的。打扰了!
traceless 2010-01-18
  • 打赏
  • 举报
回复
记得如果贴代码的话,尽量缩减到能反映问题就行

你这个情况要贴到能运行。。。
liujiaji 2010-01-18
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 traceless 的回复:]
你这样来可不是办法呀 你又不看书,有没有指导者

要么你写个接口,定好接口,参数都是干什么的,然后晚上回去帮你弄弄

要么你就把整个代码贴出来,直接帮你修改 来得快


[/Quote]
好的,我整理一下。
traceless 2010-01-18
  • 打赏
  • 举报
回复
你这样来可不是办法呀 你又不看书,有没有指导者

要么你写个接口,定好接口,参数都是干什么的,然后晚上回去帮你弄弄

要么你就把整个代码贴出来,直接帮你修改 来得快

加载更多回复(6)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧