How to get IDXGISurface data from IDXGISwapChain1 - windows

I use dxgi to capture window, since the windows maybe resized, so I use IDXGISwapChain1 and recreate framepool, but now I can't get the surface since GetRestrictToOutput always return null.
void OnFrameArrived(winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const &sender,winrt::Windows::Foundation::IInspectable const &)
{
const winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame frame = sender.TryGetNextFrame();
auto swapChainResizedToFrame = TryResizeSwapChain(frame);
winrt::com_ptr<ID3D11Texture2D> backBuffer;
winrt::check_hresult(m_swapChain->GetBuffer(0, winrt::guid_of<ID3D11Texture2D>(), backBuffer.put_void()));
winrt::com_ptr<ID3D11Texture2D> frameSurface = GetDXGIInterfaceFromObject<ID3D11Texture2D>(frame.Surface());
m_d3dContext->CopyResource(backBuffer.get(), frameSurface.get());
DXGI_PRESENT_PARAMETERS presentParameters{};
m_swapChain->Present1(1, 0, &presentParameters);
//winrt::com_ptr<IDXGIOutput> dxgiOutput = nullptr;
IDXGIOutput* dxgiOutput = nullptr;
BOOL full;
m_swapChain->GetRestrictToOutput(&dxgiOutput);
if(dxgiOutput!=nullptr){
std::cerr <<"33333333333333"<<std::endl;
...
}
m_framePool.Recreate(m_device, m_pixelFormat, 2, m_lastSize);
If I use getbuffer to get the image data, if the window size is changed, then the image is black, the code is as below:
winrt::com_ptr<ID3D11Texture2D> renderBuffer;
winrt::check_hresult(m_swapChain->GetBuffer(0, winrt::guid_of<ID3D11Texture2D>(), renderBuffer.put_void()));
if(renderBuffer != nullptr){
D3D11_TEXTURE2D_DESC desc;
renderBuffer->GetDesc(&desc);
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
winrt::com_ptr<ID3D11Texture2D> textureCopy;
auto d3dDevice = GetDXGIInterfaceFromObject<ID3D11Device>(m_device);
winrt::check_hresult(d3dDevice->CreateTexture2D(&desc, nullptr, textureCopy.put()));
m_d3dContext->CopyResource(textureCopy.get(), renderBuffer.get());
winrt::com_ptr<IDXGISurface> dxgi_surface = nullptr;
HRESULT hr = textureCopy->QueryInterface(__uuidof(IDXGISurface), (void **)(&dxgi_surface));
DXGI_MAPPED_RECT mapped_rect;
hr = dxgi_surface->Map(&mapped_rect, DXGI_MAP_READ);
unsigned int imgSize = desc.Width * desc.Height * 4;
uint8_t* buffer = new uint8_t[imgSize];
int dst_rowpitch = desc.Width * 4;
for (unsigned int h = 0; h < desc.Height; h++) {
memcpy_s(buffer + h * dst_rowpitch, dst_rowpitch, (BYTE*)mapped_rect.pBits + h * mapped_rect.Pitch, min(mapped_rect.Pitch, dst_rowpitch));
}
dxgi_surface->Unmap();

Related

Making a Cubemap in DX11 from 6 Textures

I want to load in a skysphere, I know how to do it using a dds file, but I want to try and do it from 6 separate texture files.
The problem I have is that when I load in the texturecube, only 3 separate textures are visible, the other 3 are not. I'll show you my code and how it looks in Nsight. I am right now using just 6 different uniform colored png files, they are all 512x512 in size.
std::vector<std::string> paths = { "../Resources/Textures/posX.png", "../Resources/Textures/negX.png",
"../Resources/Textures/posY.png",
"../Resources/Textures/negY.png",
"../Resources/Textures/posZ.png", "../Resources/Textures/negZ.png" };
ID3D11Texture2D* cubeTexture = NULL;
WRL::ComPtr<ID3D11ShaderResourceView> shaderResourceView = NULL;
//Description of each face
D3D11_TEXTURE2D_DESC texDesc = {};
texDesc.Width = 512;
texDesc.Height = 512;
texDesc.MipLevels = 1;
texDesc.ArraySize = 6;
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texDesc.CPUAccessFlags = 0;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
//The Shader Resource view description
D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc = {};
SMViewDesc.Format = texDesc.Format;
SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
SMViewDesc.TextureCube.MipLevels = texDesc.MipLevels;
SMViewDesc.TextureCube.MostDetailedMip = 0;
D3D11_SUBRESOURCE_DATA pData[6] = {};
for (int i = 0; i < 6; i++)
{
ID3D11Resource* res = nullptr;
std::wstring pathWString(paths[j].begin(), paths[j].end());
HRESULT hr = DirectX::CreateWICTextureFromFileEx(Renderer::getDevice(), pathWString.c_str(), 0, D3D11_USAGE_STAGING, 0, D3D11_CPU_ACCESS_READ, 0,
WIC_LOADER_FLAGS::WIC_LOADER_DEFAULT,
&res, 0);
assert(SUCCEEDED(hr));
D3D11_MAPPED_SUBRESOURCE destRes = {};
Renderer::getContext()->Map(res, 0, D3D11_MAP_READ, 0, &destRes);
pData[i].pSysMem = destRes.pData;
pData[i].SysMemPitch = destRes.RowPitch;
pData[i].SysMemSlicePitch = destRes.DepthPitch;
Renderer::getContext()->Unmap(res, 0);
RELEASE_COM(res);
}
Renderer::getDevice()->CreateTexture2D(&texDesc, &pData[0], &cubeTexture);
Renderer::getDevice()->CreateShaderResourceView(cubeTexture, &SMViewDesc, shaderResourceView.GetAddressOf());
When graphics debugging, this is what the cubemap looks like, 3 textures are loaded in twice, overwriting the other 3.
When reading the documentation it says subresource should be relating to mip levels.
If I loop 9 times instead of 6, the other 3 images are shown instead of these current 3. All 6 should have unique colors.
What I'm doing in the code is creating a Texture2D Description, a Shader Resource View Descriptuion, then I try to fetch data from imported images using WIC, I put it in a resource then map that to a subresource struct.
When looking at the addresses of the subresource, all 6 are always unique so it seems they load in the textures correctly, I have tried moving around the rowpitch, changing the size of the image but it only seems to affect the single images inside the textureCube, it doesn't seem to move around the duplicates if you understand what I mean.
Any help is greatly appreciated.
So I found some code from a Frank D Luna example doing something else.
Here is the code I use that works, mip levels had to be taken into account.
I hope this helps if someone in the future has a similar issue.
ID3D11Texture2D* cubeTexture = NULL;
WRL::ComPtr<ID3D11ShaderResourceView> shaderResourceView = NULL;
//Description of each face
D3D11_TEXTURE2D_DESC texDesc = {};
D3D11_TEXTURE2D_DESC texDesc1 = {};
//The Shader Resource view description
D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc = {};
ID3D11Texture2D* tex[6] = { nullptr, nullptr, nullptr,nullptr, nullptr, nullptr };
for (int i = 0; i < 6; i++)
{
std::wstring pathWString(paths[i].begin(), paths[i].end());
HRESULT hr = DirectX::CreateWICTextureFromFileEx(Renderer::getDevice(), pathWString.c_str(), 0, D3D11_USAGE_STAGING, 0, D3D11_CPU_ACCESS_READ| D3D11_CPU_ACCESS_WRITE, 0,
WIC_LOADER_FLAGS::WIC_LOADER_DEFAULT,
(ID3D11Resource**)&tex[i], 0);
assert(SUCCEEDED(hr));
}
tex[0]->GetDesc(&texDesc1);
texDesc.Width = texDesc1.Width;
texDesc.Height = texDesc1.Height;
texDesc.MipLevels = texDesc1.MipLevels;
texDesc.ArraySize = 6;
texDesc.Format = texDesc1.Format;
texDesc.CPUAccessFlags = 0;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
SMViewDesc.Format = texDesc.Format;
SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
SMViewDesc.TextureCube.MipLevels = texDesc.MipLevels;
SMViewDesc.TextureCube.MostDetailedMip = 0;
Renderer::getDevice()->CreateTexture2D(&texDesc, NULL, &cubeTexture);
for (int i = 0; i < 6; i++)
{
for (UINT mipLevel = 0; mipLevel < texDesc.MipLevels; ++mipLevel)
{
D3D11_MAPPED_SUBRESOURCE mappedTex2D;
HRESULT hr = (Renderer::getContext()->Map(tex[i], mipLevel, D3D11_MAP_READ, 0, &mappedTex2D));
assert(SUCCEEDED(hr));
Renderer::getContext()->UpdateSubresource(cubeTexture,
D3D11CalcSubresource(mipLevel, i, texDesc.MipLevels),
0, mappedTex2D.pData, mappedTex2D.RowPitch, mappedTex2D.DepthPitch);
Renderer::getContext()->Unmap(tex[i], mipLevel);
}
}
for (int i = 0; i < 6; i++)
{
RELEASE_COM(tex[i]);
}
Renderer::getDevice()->CreateShaderResourceView(cubeTexture, &SMViewDesc, shaderResourceView.GetAddressOf());

copy d3d11texture from another device

**CopyResource is not woorking,everyone knows why?i have setted GetSharedHandle and OpenSharedResource.
//desc1
m_desc.Width = rendererInfo.SrcBounds.Width;
m_desc.Height = rendererInfo.SrcBounds.Height;
m_desc.Format = rendererInfo.SrcFormat;
m_desc.ArraySize = 1;
m_desc.BindFlags = 0;
m_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
m_desc.SampleDesc.Count = 1;
m_desc.SampleDesc.Quality = 0;
m_desc.MipLevels = 1;
m_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
m_desc.Usage = D3D11_USAGE_STAGING;
m_destdesc = m_desc;
//desc2
m_destdesc.Usage = D3D11_USAGE_DEFAULT;
m_destdesc.CPUAccessFlags = 0;
...
IDXGIResource* copyResource = nullptr;
hr = m_copyTexture2D->QueryInterface(__uuidof(IDXGIResource), (void**)&copyResource);
if (FAILED(hr))
return false;
HANDLE shareHandle = nullptr;
hr = copyResource->GetSharedHandle(&shareHandle);
copyResource->Release();
copyResource = nullptr;
ID3D11Resource* tempResource = nullptr;
ID3D11Texture2D* tempTex2D = nullptr;
hr = m_device->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource), (void**)(&tempResource));
tempResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)(&tempTex2D));
ID3D11Device* ppDevice = nullptr;
tempTex2D->GetDevice(&ppDevice);
tempResource->Release();
//DirectX::SaveWICTextureToFile(m_deviceContext, tempTex2D, GUID_ContainerFormatJpeg, L"d:/glinterop2.jpg");
ID3D11DeviceContext* tempContext = nullptr;
ppDevice->GetImmediateContext(&tempContext);
tempContext->CopyResource(m_destTexture2D, tempTex2D);
tempContext->Flush();
ID3D11DeviceContext* destContext = nullptr;
pContext->getCurrentD3D11Device()->GetImmediateContext(&destContext);
DirectX::SaveWICTextureToFile(destContext, m_destTexture2D, GUID_ContainerFormatJpeg, L"d:/glinterop3.jpg");
//destContext->Release();
//tempTex2D->Release();
if (m_deskDupl) {
hr = m_deskDupl->ReleaseFrame();
}**
IDXGIResource* copyResource = nullptr;
hr = m_destTexture2D->QueryInterface(__uuidof(IDXGIResource), (void**)&copyResource);
if (FAILED(hr))
return false;
HANDLE shareHandle = nullptr;
hr = copyResource->GetSharedHandle(&shareHandle);
copyResource->Release();
copyResource = nullptr;
ID3D11Texture2D* tempTex2D = nullptr;
hr = m_device->OpenSharedResource(shareHandle, __uuidof(ID3D11Texture2D), (void**)(&tempTex2D));
m_deviceContext->CopyResource(tempTex2D, m_copyTexture2D);
m_deviceContext->Flush();
ID3D11Device* ppDevice = nullptr;
tempTex2D->GetDevice(&ppDevice);
ID3D11DeviceContext* tempContext = nullptr;
ppDevice->GetImmediateContext(&tempContext);
DirectX::SaveWICTextureToFile(tempContext, tempTex2D, GUID_ContainerFormatJpeg, L"d:/glinterop2.jpg");
tempTex2D->Release();
tempTex2D = nullptr;
tempContext->Release();
tempContext = nullptr;
ppDevice->Release();
ppDevice = nullptr;
DirectX::SaveWICTextureToFile(m_destContext, m_destTexture2D, GUID_ContainerFormatJpeg, L"d:/glinterop3.jpg");
if (m_deskDupl) {
hr = m_deskDupl->ReleaseFrame();
}

How to refresh OnPaint() function; Window Update is not working

This is my code:
void CChildView::OnPaint()
{
CPaintDC dc(this);
CBitmap b; b.LoadBitmap(IDB_BITMAP1);
CDC memdc; memdc.CreateCompatibleDC(&dc);
auto prev = memdc.SelectObject(&b);
BITMAP bmp; b.GetBitmap(&bmp);
int bitmap_height = bmp.bmHeight;
int bitmap_width = bmp.bmWidth;
if (!painted) {
nrows = divide(bitmap_height, 8);
ncols = divide(bitmap_width, 8);
piece_height = bitmap_height / nrows;
piece_width = bitmap_width / ncols;
int number_of_tiles = nrows * ncols;
positions.resize(number_of_tiles);
std::iota(positions.begin(), positions.end(), 0);
empty = positions.size() - 1;//prazna pločica je zadnja
std::shuffle(positions.begin(), positions.end(), std::mt19937{ std::random_device{}() });
painted = true;
}
for (int i = 0; i < positions.size()-1; ++i) {
int row_dest = positions[i] / ncols;
int col_dest = positions[i] % ncols;
int row_src = i / ncols;
int col_src = i % ncols;
int x_src = col_src * piece_width;
int y_src = row_src * piece_height;
int x_dest = col_dest * piece_width;
int y_dest = row_dest * piece_height;
dc.BitBlt(x_dest, y_dest, piece_width, piece_height, &memdc, x_src, y_src, SRCCOPY);
dc.SelectObject(prev);
}
}
void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call def
CWnd::OnLButtonDown(nFlags, point);
//koordinate gdje je korisnik kliknuo
int row = point.y / piece_height;
int col = point.x / piece_width;
int empty_row = empty / ncols;
int empty_col = empty % ncols;
bool slide = false;
switch (abs(row - empty_row)) {
case 1:
if (abs(col==empty_col))
slide = true;
break;
case 0:
if (abs(col-empty_col==1))
slide = true;
break;
}
if (slide) {
int old_index = row * ncols + col;
positions[old_index] = positions[empty];
empty = old_index;
CWnd::InvalidateRect(NULL, FALSE);
CWnd::UpdateWindow();
}
}
I am trying to write a program that is called SlidingPuzzle. I managed to divide a bitmap into rectangles and shuffle them randomly. However, when I click on a rectangle there is no change. I suppose that UpdateWindow() is not working. It should refresh OnPaint() function. Can someone please help me, what am I doing wrong?

rgb32 data resource mapping. using directx memcpy

I have been trying to solve the problem for a month with googling.
But Now I have to ask for help here.
I want to render using ffmpeg decoded frame.
and using frame(it converted to RGB32 format), I try to render frame with DX2D texture.
ZeroMemory(&TextureDesc, sizeof(TextureDesc));
TextureDesc.Height = pFrame->height;
TextureDesc.Width = pFrame->width;
TextureDesc.MipLevels = 1;
TextureDesc.ArraySize = 1;
TextureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; //size 16
TextureDesc.SampleDesc.Count = 1;
TextureDesc.SampleDesc.Quality = 0;
TextureDesc.Usage = D3D11_USAGE_DYNAMIC;
TextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
TextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
TextureDesc.MiscFlags = 0;
result = m_device->CreateTexture2D(&TextureDesc, NULL, &m_2DTex);
if (FAILED(result)) return false;
ShaderResourceViewDesc.Format = TextureDesc.Format;
ShaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
ShaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
ShaderResourceViewDesc.Texture2D.MipLevels = 1;
D3D11_MAPPED_SUBRESOURCE S_mappedResource_tt = { 0, };
ZeroMemory(&S_mappedResource_tt, sizeof(D3D11_MAPPED_SUBRESOURCE));
result = m_deviceContext->Map(m_2DTex, 0, D3D11_MAP_WRITE_DISCARD, 0, &S_mappedResource_tt);
if (FAILED(result)) return false;
BYTE* mappedData = reinterpret_cast<BYTE *>(S_mappedResource_tt.pData);
for (auto i = 0; i < pFrame->height; ++i) {
memcpy(mappedData, pFrame->data, pFrame->linesize[0]);
mappedData += S_mappedResource_tt.RowPitch;
pFrame->data[0] += pFrame->linesize[0];
}
m_deviceContext->Unmap(m_2DTex, 0);
result = m_device->CreateShaderResourceView(m_2DTex, &ShaderResourceViewDesc, &m_ShaderResourceView);
if (FAILED(result)) return false;
m_deviceContext->PSSetShaderResources(0, 1, &m_ShaderResourceView);
but it shows me just black screen(nothing render).
I guess it's wrong memcpy size.
The biggest problem is that I don't know what is the problem.
Question 1 :
It has any problem creating 2D texture for mapping?
Question 2 :
What size of the memcpy parameters should I enter (related to formatting)?
I based on the link below.
[1]https://www.gamedev.net/forums/topic/667097-copy-2d-array-into-texture2d/
[2]https://www.gamedev.net/forums/topic/645514-directx-11-maping-id3d11texture2d/
[3]https://www.gamedev.net/forums/topic/606100-solved-dx11-updating-texture-data/
Thank U for watching, Please reply.
Nobody reply. I solved my issue.
I have modified some code and I'm not sure if it solves the problem. The problem with the black screen Reason is my matrix.
D3D11_TEXTURE2D_DESC TextureDesc;
D3D11_RENDER_TARGET_VIEW_DESC RenderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC ShaderResourceViewDesc;
ZeroMemory(&TextureDesc, sizeof(TextureDesc));
TextureDesc.Height = pFrame->height;
TextureDesc.Width = pFrame->width;
TextureDesc.MipLevels = 1;
TextureDesc.ArraySize = 1;
TextureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;/*DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;*/ //size 32bit
TextureDesc.SampleDesc.Count = 1;
TextureDesc.SampleDesc.Quality = 0;
TextureDesc.Usage = D3D11_USAGE_DYNAMIC;
TextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
TextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
TextureDesc.MiscFlags = 0;
DWORD* pInitImage = new DWORD[pFrame->width*pFrame->height];
memset(pInitImage, 0, sizeof(DWORD)*pFrame->width*pFrame->height);
D3D11_SUBRESOURCE_DATA InitData;
InitData.pSysMem = pInitImage;
InitData.SysMemPitch = pFrame->width*sizeof(DWORD);
InitData.SysMemSlicePitch = 0;
result = m_device->CreateTexture2D(&TextureDesc, &InitData, &m_2DTex);
if (FAILED(result)) return false;
ShaderResourceViewDesc.Format = TextureDesc.Format;
ShaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
ShaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
ShaderResourceViewDesc.Texture2D.MipLevels = 1;
result = m_device->CreateShaderResourceView(m_2DTex, &ShaderResourceViewDesc, &m_ShaderResourceView);
if (FAILED(result)) return false;
D3D11_MAPPED_SUBRESOURCE S_mappedResource_tt;
ZeroMemory(&S_mappedResource_tt, sizeof(S_mappedResource_tt));
DWORD Stride = pFrame->linesize[0];
result = m_deviceContext->Map(m_2DTex, 0, D3D11_MAP_WRITE_DISCARD, 0, &S_mappedResource_tt);
if (FAILED(result)) return false;
BYTE * pFrameData = pFrame->data[0]; // now we have a pointer that points to begin of the destination buffer
BYTE* mappedData = (BYTE *)S_mappedResource_tt.pData;// +S_mappedResource_tt.RowPitch;
for (auto i = 0; i < pFrame->height; i++) {
memcpy(mappedData, pFrameData, Stride);
mappedData += S_mappedResource_tt.RowPitch;
pFrameData += Stride;
}
m_deviceContext->Unmap(m_2DTex, 0);
It works vell. I hope that it will be helpful to those who are doing the same thing with me.

Remote IO Play with constant noise

guys! I have a trouble with using remote IO to playback a stream audio.I verified the PCM frame data before I put it in,it's correct.So I'm confused.Could you help me? Thanks a lot!
Below is my codes.
-
(void)initializeAudioPlay
{
OSStatus status;
// Describe audio component
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// Get component
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
// Get audio units
status = AudioComponentInstanceNew(inputComponent, &audioPlayUnit);
[self checkStatus:status];
// Enable IO for playback
UInt32 flag = 1;
//kAUVoiceIOProperty_VoiceProcessingEnableAGC
status = AudioUnitSetProperty(audioPlayUnit, kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input, kOutputBus, &flag, sizeof(flag));
[self checkStatus:status];
// Describe format
AudioStreamBasicDescription audioFormat;
memset(&audioFormat, 0, sizeof(audioFormat));
audioFormat.mSampleRate = 8000;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagsCanonical;//kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsSignedInteger;
/*kAudioFormatFlagsCanonical
| (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift)*/
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 1;
audioFormat.mBitsPerChannel = 16;
audioFormat.mBytesPerFrame = (audioFormat.mBitsPerChannel/8) * audioFormat.mChannelsPerFrame;
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame;
// Apply format
status = AudioUnitSetProperty(audioPlayUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kOutputBus,
&audioFormat,
sizeof(audioFormat));
[self checkStatus:status];
float value = (float)10 / 255.0;
AudioUnitSetParameter(audioPlayUnit, kAudioUnitParameterUnit_LinearGain, kAudioUnitScope_Input, 0, value, 0);
AudioChannelLayout new_layout;
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
AudioUnitSetProperty( audioPlayUnit,
kAudioUnitProperty_AudioChannelLayout,
kAudioUnitScope_Global,
0, &new_layout, sizeof(new_layout) );
UInt32 bypassEffect = kAudioUnitProperty_RenderQuality;
status = AudioUnitSetProperty(audioPlayUnit,
kAudioUnitProperty_RenderQuality,
kAudioUnitScope_Global,
0,
&bypassEffect,
sizeof(bypassEffect));
[self checkStatus:status];
// Set output callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = playCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(audioPlayUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
[self checkStatus:status];
flag = 0;
// Initialize
status = AudioUnitInitialize(audioPlayUnit);
[self checkStatus:status];
DGLog(#"audio play unit initialize = %d", status);
circularBuf = [[CircularBuf alloc] initWithBufLen:kBufferLength];
/*
AudioSessionInitialize(NULL, NULL, NULL, NULL);
Float64 rate =32000.0;
AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(rate), &rate);
Float32 volume=20.0;
UInt32 size = sizeof(Float32);
AudioSessionSetProperty(
kAudioSessionProperty_PreferredHardwareIOBufferDuration,
&size, &volume);
//float aBufferLength = 0.185759637188209;
//AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(aBufferLength), &aBufferLength);
AudioSessionSetActive(YES);
*/
AudioSessionInitialize(NULL, NULL, NULL, nil);
AudioSessionSetActive(true);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;
/* for Iphone we need to do this to route the audio to speaker */
status= AudioSessionSetProperty (
kAudioSessionProperty_AudioCategory,
sizeof (sessionCategory),
&sessionCategory
);
//NSLog(#"Error: %d", status);
//
// UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
// status = AudioSessionSetProperty (
// kAudioSessionProperty_OverrideAudioRoute,
// sizeof (audioRouteOverride),
// &audioRouteOverride);
UInt32 audioMixed = 1;
status = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryMixWithOthers,
sizeof (audioMixed),
&audioMixed);
}
- (void)processAudio:(AudioBuffer *)buffer
{
short pcmTemp[160];
unsigned char * amrBuffer=NULL;
AudioUnitSampleType sample;
int i = 0;
int j = 0;
if ([circularBuf isReadTwoRegion]) {
amrBuffer = [circularBuf ReadData];
} else {
amrBuffer = [circularBuf ReadData];
i = [circularBuf ReadPos];
}
j = i + circularBuf.Length;
if (j - i >= 320) {
memcpy((void*)pcmTemp, (void*)amrBuffer, 320);
for(i=0; i<160; i++)
{
sample = 3.162277*pcmTemp[i];//10db
if(sample > 32767)sample = 32767;
else if(sample < -32768)sample = -32768;
buffData[i] = sample;
}
memcpy(buffer->mData, buffData, buffer->mDataByteSize);
[circularBuf AdvanceReadPos:320];
}
else
{
memset(buffer->mData, 0, buffer->mDataByteSize);
}
}
/**
This callback is called when the audioUnit needs new data to play through the
speakers. If you don't have any, just don't write anything in the buffers
*/
static OSStatus playCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData) {
// Notes: ioData contains buffers (may be more than one!)
// Fill them up as much as you can. Remember to set the size value in each buffer to match how
// much data is in the buffer.
AudioPlay *audioPlay = (AudioPlay *)inRefCon;
for ( int i=0; i < ioData->mNumberBuffers; i++ ) {
memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
}
ioData->mBuffers[0].mNumberChannels = 1;
[audioPlay processAudio:&ioData->mBuffers[0]];
return noErr;
}

Resources