Part3:The Play State

本文详细介绍了 TetroGL 游戏的核心玩法及其实现逻辑,包括不同形状方块的旋转、移动机制,以及游戏矩阵中消除行的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来自:http://www.codeproject.com/Articles/30775/TetroGL-An-OpenGL-Game-Tutorial-in-C-for-Win32-pla

目录:

1、The Play State

2、补充    简单使用

1、The Play State

This state is the most complicated one, because it is there that all the game logic is handled. The play state delegates most of the logic to theCBlocksMatrixclass, which is responsible of the management of the playing area. There are 7 different shapes (also called tetrads), which are named by a letter depending on their shape: I, O, Z, S, T, L and J. Each of these tetrads has a specific class to handle it. It is done so because there is no generic way to handle all the different tetrads. For instance, rotations are not always done in the same way: The I tetrad (the line) has only two different position (vertical and horizontal), you don't simply rotate all the cells around a point. So, for this reason, each tetrad has to be handled separately. They all inherits from theCTetradclass, which looks like:

// Base class for all shapes (tetrad)
class CTetrad
{
public:
  // Construct a new tetrad. The image of the block used to draw
  // the tetrad is loaded depending of the tetrad color.
  CTetrad(CBlocksMatrix* pParent, EBlockColor blockColor) 
    : m_pParentMatrix(pParent), m_iXPos(4), m_iYPos(0), 
      m_Orientation(Rotation0), m_pBlockImg(NULL), m_BlockColor(blockColor)  
  { 
    switch (blockColor)
    {
    case bcCyan:
      m_pBlockImg = CImage::CreateImage("Block.PNG",
          TRectanglei(0,BLOCK_HEIGHT,0,BLOCK_WIDTH));
      break;
    case bcBlue:
      m_pBlockImg = CImage::CreateImage("Block.PNG",
          TRectanglei(0,BLOCK_HEIGHT,BLOCK_WIDTH,2*BLOCK_WIDTH));
      break;
    case bcOrange:
      m_pBlockImg = CImage::CreateImage("Block.PNG",
          TRectanglei(0,BLOCK_HEIGHT,2*BLOCK_WIDTH,3*BLOCK_WIDTH));
      break;
    case bcYellow:
      m_pBlockImg = CImage::CreateImage("Block.PNG",
          TRectanglei(0,BLOCK_HEIGHT,3*BLOCK_WIDTH,4*BLOCK_WIDTH));
      break;
    case bcGreen:
      m_pBlockImg = CImage::CreateImage("Block.PNG",
          TRectanglei(0,BLOCK_HEIGHT,4*BLOCK_WIDTH,5*BLOCK_WIDTH));
      break;
    case bcPurple:
      m_pBlockImg = CImage::CreateImage("Block.PNG",
          TRectanglei(BLOCK_HEIGHT,2*BLOCK_HEIGHT,0,BLOCK_WIDTH));
      break;
    case bcRed:
      m_pBlockImg = CImage::CreateImage("Block.PNG",
          TRectanglei(BLOCK_HEIGHT,2*BLOCK_HEIGHT,BLOCK_WIDTH,2*BLOCK_WIDTH));
      break;
    }
  }
  virtual ~CTetrad() { }

  // Tries to rotate the tetrad. If it can't be rotated, 
  // the function returns false.
  virtual bool Rotate() = 0;
  // Tries to move the tetrad to the left. If it can't be 
  // moved, the function returns false.
  virtual bool MoveLeft() = 0;
  // Tries to move the tetrad to the right. If it can't be 
  // moved, the function returns false.
  virtual bool MoveRight() = 0;
  // Tries to move the tetrad down. If it can't be 
  // moved, the function returns false.
  virtual bool MoveDown() = 0;

  // Ask the tetrad to fill the cells in the matrix.
  // This function is called when the tetrad is positioned.
  virtual void FillMatrix() = 0;
  // Checks if the tetrad is at a valid position (do not 
  // overlap with a filled cell in the matrix). This is 
  // called when the tetrad is created to check for game over.
  virtual bool IsValid() = 0;

  // Draw the tetrad at its position in the matrix.
  virtual void Draw() = 0;
  // Draw the tetrad somewhere on the screen (used to
  // display the next shape). The tetrad is centered
  // in the rectangle.
  virtual void DrawOnScreen(const TRectanglei& rect) = 0;

protected:
  // The play area in which the tetrad is used
  CBlocksMatrix* m_pParentMatrix;

  // The position in the play area (in
  // blocks).
  int m_iXPos;
  int m_iYPos;

  enum EOrientation
  {
    Rotation0,
    Rotation90,
    Rotation180,
    Rotation270,
  };
  // Orientation of the tetrad
  EOrientation m_Orientation;

  // The block image use to draw the tetrad.
  TImagePtr m_pBlockImg;
  // The block color.
  EBlockColor m_BlockColor;
};

The child classes implement those virtual methods. They interract with the CBlocksMatrix class to check if some cells are free or not. Here is an example of the rotation function for the Z tetrad:

bool CTetrad_Z::Rotate()
{
  bool bSuccess = false;
  switch (m_Orientation)
  {
  case Rotation0:
  case Rotation180:
    if (m_pParentMatrix->IsCellFree(m_iXPos,m_iYPos-1) &&

      m_pParentMatrix->IsCellFree(m_iXPos-1,m_iYPos+1) )
    {
      m_Orientation = Rotation90;
      bSuccess = true;
    }
    break;

  case Rotation90:
  case Rotation270:
    if (m_pParentMatrix->IsCellFree(m_iXPos,m_iYPos+1) &&
      m_pParentMatrix->IsCellFree(m_iXPos+1,m_iYPos+1))
    {
      m_Orientation = Rotation0;
      bSuccess = true;
    }
    break;
  }
  return bSuccess;
}
Depending of the current rotation of the tetrad, it will check if the cells that will be occupied after the rotation are free or not. If they are free, the m_Orientation member is updated and the function returns true. The other move or rotate functions of all the tetrads are similar, so I won't put here the code for all of them. The Drawfunction is not very difficult neither:

void CTetrad_Z::Draw()
{
  int screenX=0, screenY=0; 

  switch (m_Orientation)
  {
  case Rotation0:
  case Rotation180:
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos-1,m_iYPos,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos  ,m_iYPos,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos  ,m_iYPos+1,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos+1,m_iYPos+1,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    break;

  case Rotation90:
  case Rotation270:
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos  ,m_iYPos-1,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos  ,m_iYPos  ,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos-1,m_iYPos  ,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    m_pParentMatrix->GetScreenPosFromCell(m_iXPos-1,m_iYPos+1,screenX,screenY);
    m_pBlockImg->BlitImage(screenX,screenY);
    break;
  }
}

The screen position of a cell can be retrieved from the CBlocksMatrix class (remember that the m_iXPos and m_iYPos members are the position in the matrix and are not screen positions).

The CBlocksMatrix is responsible to handle all the logic related to checking filled lines and removing them. Let's first look at the class header, we will look at the implementation of some functions later:

// Class managing the playing area (where the shapes are
// falling). It handles all the logic related to lines.
class CBlocksMatrix
{
public:
  // Constructor and destructor
  CBlocksMatrix(CMatrixEventsListener* pListener, int xPos, int yPos);
  ~CBlocksMatrix();

  // Draw and update the matrix
  void Draw();
  void Update(DWORD dwCurrentTime);
  // Reset the matrix to its initial state
  void Reset();

  // Move the current shape
  void ShapeLeft();
  void ShapeRight();
  void ShapeDown();
  void ShapeRotate();

  // Check if the specified cell is free or not.
  bool IsCellFree(int XPos, int YPos);
  // Fill the specified cell with a specific block color
  void FillCell(int XPos, int YPos, EBlockColor BlockColor);
  // Transform a cell coordinates into screen coordinates.
  void GetScreenPosFromCell(int cellXPos, int cellYPos, 
    int& screenXPos, int& screenYPos);

  // Returns the next shape
  CTetrad* GetNextShape() const  { return m_pNextShape; }

  // Sets/Gets the time between two update of the current
  // shape (determines the speed at which it falls).
  void SetTetradUpdate(int iNewUpdate)  { m_iTetradUpdate = iNewUpdate; }
  int  GetTetradUpdate() const  { return m_iTetradUpdate; }

private:
  // Check if there are lines completed in the
  // matrix. This returns true if at least one
  // line is complete
  bool CheckMatrix();
  // Check if the specified line is currently being
  // removed
  bool IsLineRemoved(int iRow);
  // Remove the lines that are complete from the
  // matrix and adjust the remaining blocks.
  void RemoveLines();
  // Tries to create a new shape. If this is not
  // possible (e.g. matrix full), m_bGameOver is
  // set to true.
  void NewShape();

  // The screen coordinates of the top-left 
  // corner.
  int m_iXPos;
  int m_iYPos;

  // The matrix of blocks which are already filled
  int m_pBlocksMatrix[MATRIX_WIDTH][MATRIX_HEIGHT];

  // The images of the 7 different blocks
  TImagePtr m_pBlockImg[7];

  // The tetrad factory
  CTetradFactory m_TetradFactory;
  // Current shape that the player manipulates
  CTetrad* m_pTetrad;
  // Next shape
  CTetrad* m_pNextShape;
  // The last move down of the current shape
  DWORD m_dwLastShapeDown;

  // Flag indicating that one or more
  // lines are being removed (blinking)
  bool m_bRemovingLine;
  // The number of times the line being removed
  // has already blinked.
  int  m_iLineBlinkCount;
  // Specify if the the line being removed is currently
  // visible or not (for blinking)
  bool m_bLineBlinkOn;
  // Vector containing the line numbers of the
  // lines being removed.
  std::vector<int> m_vecLinesRemoved;

  // The event listener
  CMatrixEventsListener* m_pListener;
  // Time (in msec) before the tetrad is moved down
  // one step.
  int m_iTetradUpdate;

  // Flag indicating a game over.
  bool m_bGameOver;
};

The ShapeLeft, ShapeRight, ShapeRotateand ShapeDownfunctions are simply redirected to the current tetrad ( m_pTetrad). The ShapeDownfunction does a bit more, because if a tetrad cannot move down, some special checks need to be done:

void CBlocksMatrix::ShapeDown()
{
  if (m_pTetrad && !m_pTetrad->MoveDown())
  {
    // If the current shape can't move down,
    // we ask it to fill the matrix.
    m_pTetrad->FillMatrix();
    // Then delete the current shape
    delete m_pTetrad; 
    m_pTetrad = NULL;
    
    // We then check if no lines have been completed
    // and create the next shape. The m_bGameOver flag
    // can be set in this NewShape function.
    if (!CheckMatrix())
      NewShape();
  }
  // Set the last update (down) of the shape to 
  // the current time.
  m_dwLastShapeDown = GetCurrentTime();
}

If the shape cannot be moved down (the MoveDownfunction returns false), we first ask it to fill the cells of the matrix where it is located, then delete it. We then check if at least one line of the matrix is complete: TheCheckMatrix function returns true if at least one line is completed and if that is the case, it will push the line numbers of the ones that are filled in them_vecLinesRemoved vector and set m_bRemovingLine to true. If no lines were completed, we try to create a new shape by callingNewShape. If the shape cannot be created (because the matrix is full), them_bGameOver flag will be set to true.

The Update function only checks if the current shape should be moved down:

void CBlocksMatrix::Update(DWORD dwCurrentTime)
{
  if (!m_bGameOver)
  {
    // Check if the current shape should be moved down
    if (dwCurrentTime > m_dwLastShapeDown+m_iTetradUpdate)
      ShapeDown();
  }
}

The m_iTetradUpdate variable specifies the maximum time between two moves down of the current shape. This decreases with the level (the higher the level, the faster the shape will go down). Don't forget that the m_dwLastShapeDown variable is set to the current time in theShapeDownfunction (so if the shape is moved manually, this is also set).

Finally, the Draw function takes care of drawing the current state on the screen:

void CBlocksMatrix::Draw()
{
  int iBlockX=0, iBlockY=0;
  // If some lines are currently being removed,
  // We shouldn't draw them all.
  if (m_bRemovingLine)
  {
    for (int j=0; j<MATRIX_HEIGHT;j++)
    {
      // Don't draw the line if it is being removed and blinking off
      if (IsLineRemoved(j) && !m_bLineBlinkOn)
        continue;

      // Else draw the line
      for (int i=0; i<MATRIX_WIDTH;i++)
      {
        if (m_pBlocksMatrix[i][j])
        {
          int color = m_pBlocksMatrix[i][j]-1;
          GetScreenPosFromCell(i, j, iBlockX, iBlockY);
          m_pBlockImg[color]->BlitImage(iBlockX, iBlockY);
        }     
      }
    }

    // Switch the blinking
    if (m_bLineBlinkOn)
      m_bLineBlinkOn = false;
    else
      m_bLineBlinkOn = true;
    m_iLineBlinkCount++;
    // If blink count equals 10, we stop blinking and remove
    // the lines.
    if (m_iLineBlinkCount == 10)
    {
      RemoveLines();
      m_bRemovingLine = false;
      m_bLineBlinkOn = false;
      m_iLineBlinkCount = 0;
      NewShape();
    }
  }
  else 
  {
    // Draw filled blocks
    for (int j=0; j<MATRIX_HEIGHT;j)
    {
      for (int i=0; i<MATRIX_WIDTH;i++)
      {
        if (m_pBlocksMatrix[i][j])
        {
          int color = m_pBlocksMatrix[i][j]-1;
          GetScreenPosFromCell(i, j, iBlockX, iBlockY);
          m_pBlockImg[color]->BlitImage(iBlockX, iBlockY);
        }
      }
    }

    // Finally, draw the current shape
    if (!m_bGameOver)
      m_pTetrad->Draw();
  }

}

The first part of the function (if m_bRemovingLine is true) is only executed when we are removing lines (the lines which are complete will blink before being removed). Remember that in order to display 'animations', the state should be saved in some way for the next frame to be displayed. That's the reason why we have to remember if the lines are currently visible or not (m_bLineBlinkOn) and the number of times they have already blinked (m_iLineBlinkCount). TheIsLineRemoved function returns true if the line passed in argument is being removed. When the blinking is finished, theRemoveLinesfunction is called which will remove the lines from the matrix and clean everything (blocks above a removed line will be moved down). The second part of the function gets executed the rest of the time (when no lines are being removed). It simply draws all the filled blocks and the current shape.

As you probably saw, there is also a CMatrixEventsListenerclass. In fact, this is just an interface that should be implemented by another class in order to be notified about some events that occurs in the blocks matrix (starting to remove lines, lines removed, game over). TheCPlayStateclass implements this interface (and its address is passed to theCBlocksMatrixwhen constructing it). This technique is used in order to reduce coupling between those classes: TheCBlocksMatrixclass becomes independant of the class which is using it and which should be notified about the events. TheCPlayState looks like:

class CPlayState : public CGameState, 
           public CMatrixEventsListener
{
public:
  ~CPlayState();

  // Implementation of specific events
  void OnKeyDown(WPARAM wKey);
  void Update(DWORD dwCurrentTime);
  void Draw();

  // Implementation of the CMatrixEventsListener class
  void OnStartRemoveLines();
  void OnLinesRemoved(int iLinesCount);
  void OnMatrixFull();

  void Reset();
  bool IsGameOver()  { return m_bGameOver; }

  // Returns the single instance
  static CPlayState* GetInstance(CStateManager* pManager);

protected:
  CPlayState(CStateManager* pManager);

private:
  // The blocks matrix class
  CBlocksMatrix* m_pMatrix;
  // The font used to draw text
  CGameFont* m_pFont;
  // The control in charge of the decreasing 
  // time for the combo score.
  CComboControl* m_pComboControl;

  // The text controls to display the current
  // information.
  CTextControl* m_pScoreControl;
  CTextControl* m_pLevelControl;
  CTextControl* m_pLinesControl;

  // The current number of lines completed
  int m_iTotalLines;
  // The current level
  int m_iCurrentLevel;
  // The current score
  int m_iCurrentScore;

  bool m_bGameOver;

  // The background image
  TImagePtr m_pBackgroundImg;
};

The main role of this class is to coordinate the different elements: The game matrix and the combo control and to manage the score and current lines completed. The implementation of the class is fairly trivial, so I won't describe it here. TheCComboControlclass handles the combo control: This control shows a decreasing time bar when a line has been completed. If a new line is completed before time is over, a multiplier is applied to the points gained for the line(s) completed. The higher the multiplier, the fastest time will decrease.

When the game is over, a semi-transparent black rectangle will be displayed over the full screen with some text on it. This is done with the help of blending: support for blending has been added in theCMainWindow::InitGL function:


// Specifies the blending function
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Enable blending
glEnable(GL_BLEND);
The glEnable(GL_BLEND) simply enables the blending, but you also have to specify a blending function. The blending function tells OpenGL how to blend the incoming pixels with the pixels present in the frame buffer. Specifying this is done through the glBlendFunc: The first argument specifies the factor to apply to the RGB components of the source pixels (the incoming pixels) and the second argument specifies the factor to apply to the destination pixels (the pixels which are already in the frame buffer). The final pixel will be the addition of the resulting values (for each components). The code we use to make the semi-transparent black screen is:


 if (m_bGameOver)
  {
    // In game over, we draw a semi-transparent black screen on top
    // of the background. This is possible because blending has 
    // been enabled.
    glColor4f(0.0,0.0,0.0,0.5);
    // Disable 2D texturing because we want to draw a non
    // textured rectangle over the screen.
    glDisable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
    glVertex3i(0,0,0);
    glVertex3i(0,600,0);
    glVertex3i(800,600,0);
    glVertex3i(800,0,0);
    glEnd();
    glEnable(GL_TEXTURE_2D);

    m_pFont->DrawText("GAME OVER",340,200);
    m_pFont->DrawText("Press Enter to continue",285,300);
  }
This means that we first select a black color with an alpha channel of 0.5 and then we draw our rectangle over the complete screen. We have to disable texturing when drawing our rectangle, because we want a non textured black rectangle.

//原文end。。。

补充:

CPlayState类的完整实现:

CPlayState::CPlayState(CStateManager* pManager)
 : CGameState(pManager), m_pMatrix(NULL), m_pFont(NULL), 
   m_pComboControl(NULL), m_pScoreControl(NULL), 
   m_pLevelControl(NULL), m_pLinesControl(NULL),
   m_iTotalLines(0), m_iCurrentLevel(0), m_ulCurrentScore(0), 
   m_bGameOver(false)
{
	AddFontResource("01 Digitall.ttf");
	m_pMatrix = new CBlocksMatrix(this,280,34);
	m_pFont = new CGameFont;
	m_pFont->CreateFont("01 Digitall", 20, FW_NORMAL);

	m_pComboControl = new CComboControl(TRectanglei(330,450,50,235),m_pFont);
	m_pScoreControl = new CTextControl(m_pFont,TRectanglei(145,210,620,730));
	m_pScoreControl->SetAlignement(CTextControl::TACenter);
	m_pScoreControl->SetTextColor(1.0f,0.588f,0.039f);
	m_pLinesControl = new CTextControl(m_pFont,TRectanglei(320,385,620,730));
	m_pLinesControl->SetAlignement(CTextControl::TACenter);
	m_pLinesControl->SetTextColor(1.0f,0.588f,0.039f);
	m_pLevelControl = new CTextControl(m_pFont,TRectanglei(500,565,620,730));
	m_pLevelControl->SetAlignement(CTextControl::TACenter);
	m_pLevelControl->SetTextColor(1.0f,0.588f,0.039f);

	m_pBackgroundImg = CImage::CreateImage("PlayBckgnd.png",TRectanglei(0,600,0,800));
}

CPlayState::~CPlayState()
{
	if (m_pMatrix)
	{
		delete m_pMatrix;
		m_pMatrix = NULL;
	}

	if (m_pFont)
	{
		delete m_pFont;
		m_pFont = NULL;
	}
	RemoveFontResource("01 Digitall.ttf");
}

CPlayState* CPlayState::GetInstance(CStateManager* pManager)
{
	static CPlayState Instance(pManager);
	return &Instance;
}

void CPlayState::Reset()
{
	m_iTotalLines = 0;
	m_iCurrentLevel = 0; 
	m_ulCurrentScore = 0;
	m_bGameOver = false;
	m_pMatrix->Reset();
	m_pComboControl->Reset();
}

void CPlayState::OnKeyDown(WPARAM wKey)
{
	switch (wKey)
	{
	case VK_UP:
		if (!m_bGameOver)
			m_pMatrix->ShapeRotate();
		break;
	case VK_DOWN:
		if (!m_bGameOver)	
			m_pMatrix->ShapeDown();
		break;
	case VK_LEFT:
		if (!m_bGameOver)
			m_pMatrix->ShapeLeft();
		break;
	case VK_RIGHT:
		if (!m_bGameOver)
			m_pMatrix->ShapeRight();
		break;
	case VK_ESCAPE:
		ChangeState(CMenuState::GetInstance(m_pStateManager));
		break;
	case VK_RETURN:
		if (m_bGameOver)
		{
			CHighScoreState* pHighScores = 
				CHighScoreState::GetInstance(m_pStateManager);
			pHighScores->SetNewHighScore(m_ulCurrentScore);
			ChangeState(pHighScores);
		}
	}
}

void CPlayState::Update(DWORD dwCurrentTime)
{
	if (!m_bGameOver)
	{
		m_pMatrix->Update(dwCurrentTime);
		m_pComboControl->Update(dwCurrentTime);
	}
}

void CPlayState::Draw()  
{ 
	m_pBackgroundImg->BlitImage(0,0);

	m_pMatrix->Draw();

	stringstream ssScore;
	ssScore << m_ulCurrentScore;
	m_pScoreControl->SetText(ssScore.str());
	m_pScoreControl->Draw();

	stringstream ssLines;
	ssLines << m_iTotalLines;
	m_pLinesControl->SetText(ssLines.str());
	m_pLinesControl->Draw();

	stringstream ssLevel;
	ssLevel << m_iCurrentLevel;
	m_pLevelControl->SetText(ssLevel.str());
	m_pLevelControl->Draw();

	if (m_pMatrix->GetNextShape())
		m_pMatrix->GetNextShape()->DrawOnScreen(TRectanglei(165,220,80,225));

	m_pComboControl->Draw();
	if (m_bGameOver)
	{
		// In game over, we draw a semi-transparent black screen on top
		// of the background. This is possible because blending has 
		// been enabled.
		glColor4f(0.0,0.0,0.0,0.5);
		// Disable 2D texturing because we want to draw a non
		// textured rectangle over the screen.
		glDisable(GL_TEXTURE_2D);
		glBegin(GL_QUADS);
		glVertex3i(0,0,0);
		glVertex3i(0,600,0);
		glVertex3i(800,600,0);
		glVertex3i(800,0,0);
		glEnd();
		glEnable(GL_TEXTURE_2D);

		m_pFont->DrawText("GAME OVER",340,200);
		m_pFont->DrawText("Press Enter to continue",285,300);
	}

}

void CPlayState::OnStartRemoveLines()
{
	m_pComboControl->Pause();
}

void CPlayState::OnLinesRemoved(int iLinesCount)
{
	m_iTotalLines += iLinesCount;
	int comboMultiplier = m_pComboControl->GetMultiplier();
	switch (iLinesCount)
	{
	case 1:
		m_ulCurrentScore += (m_iCurrentLevel+1) * 40 * comboMultiplier;
		break;
	case 2:
		m_ulCurrentScore += (m_iCurrentLevel+1) * 100 * comboMultiplier;
		break;
	case 3:
		m_ulCurrentScore += (m_iCurrentLevel+1) * 300 * comboMultiplier;
		break;
	case 4:
		m_ulCurrentScore += (m_iCurrentLevel+1) * 1200 * comboMultiplier;
		break;
	}

	if (m_iTotalLines/10 > m_iCurrentLevel)
	{
		m_iCurrentLevel++;
		int iNewUpdateRate = (int)(m_pMatrix->GetTetradUpdate() * 0.8);
		m_pMatrix->SetTetradUpdate(iNewUpdateRate);
	}
	m_pComboControl->IncreaseMultiplier();
	m_pComboControl->Unpause();
}

void CPlayState::OnMatrixFull()
{
	m_bGameOver = true;
	m_pComboControl->Pause();
}
CBlocksMatrix类的完整实现:

CBlocksMatrix::CBlocksMatrix(CMatrixEventsListener* pListener, int xPos, int yPos) 
  : m_iXPos(xPos), m_iYPos(yPos), m_pTetrad(NULL),
    m_bRemovingLine(false), m_iLineBlinkCount(0), m_bLineBlinkOn(false), 
	m_vecLinesRemoved(), m_pListener(pListener), m_iTetradUpdate(1000),
	m_bGameOver(false)
{
	// Load the block images
	m_pBlockImg[0] = CImage::CreateImage("Block.PNG",TRectanglei(0,BLOCK_HEIGHT,0,BLOCK_WIDTH));
	m_pBlockImg[1] = CImage::CreateImage("Block.PNG",TRectanglei(0,BLOCK_HEIGHT,BLOCK_WIDTH,2*BLOCK_WIDTH));
	m_pBlockImg[2] = CImage::CreateImage("Block.PNG",TRectanglei(0,BLOCK_HEIGHT,2*BLOCK_WIDTH,3*BLOCK_WIDTH));
	m_pBlockImg[3] = CImage::CreateImage("Block.PNG",TRectanglei(0,BLOCK_HEIGHT,3*BLOCK_WIDTH,4*BLOCK_WIDTH));
	m_pBlockImg[4] = CImage::CreateImage("Block.PNG",TRectanglei(0,BLOCK_HEIGHT,4*BLOCK_WIDTH,5*BLOCK_WIDTH));
	m_pBlockImg[5] = CImage::CreateImage("Block.PNG",TRectanglei(BLOCK_HEIGHT,2*BLOCK_HEIGHT,0,BLOCK_WIDTH));
	m_pBlockImg[6] = CImage::CreateImage("Block.PNG",TRectanglei(BLOCK_HEIGHT,2*BLOCK_HEIGHT,BLOCK_WIDTH,2*BLOCK_WIDTH));

	// Initialize the matrix
	for (int i=0; i<MATRIX_WIDTH;i++)
	{
		for (int j=0; j<MATRIX_HEIGHT;j++)
		{
			m_pBlocksMatrix[i][j] = bcNone;
		}
	}

	// Create the current and next shapes
	m_pTetrad = m_TetradFactory.CreateTetrad(this);
	m_pNextShape = m_TetradFactory.CreateTetrad(this);
	m_dwLastShapeDown = GetCurrentTime();
}

CBlocksMatrix::~CBlocksMatrix()
{
}

void CBlocksMatrix::Reset()
{
	for (int i=0; i<MATRIX_WIDTH;i++)
	{
		for (int j=0; j<MATRIX_HEIGHT;j++)
		{
			m_pBlocksMatrix[i][j] = bcNone;
		}
	}

	delete m_pTetrad;
	delete m_pNextShape;
	m_pTetrad = m_TetradFactory.CreateTetrad(this);
	m_pNextShape = m_TetradFactory.CreateTetrad(this);
	m_dwLastShapeDown = GetCurrentTime();

    m_bRemovingLine = m_bLineBlinkOn = false; 
	m_iLineBlinkCount = 0;
	m_vecLinesRemoved.clear();
	m_iTetradUpdate = 1000;
	m_bGameOver = false;
}

void CBlocksMatrix::Draw()
{
	int iBlockX=0, iBlockY=0;
	// If some lines are currently being removed,
	// We shouldn't draw them all.
	if (m_bRemovingLine)
	{
		for (int j=0; j<MATRIX_HEIGHT;j++)
		{
			// Don't draw the line if it is being removed and blinking off
			if (IsLineRemoved(j) && !m_bLineBlinkOn)
				continue;

			// Else draw the line
			for (int i=0; i<MATRIX_WIDTH;i++)
			{
				if (m_pBlocksMatrix[i][j])
				{
					int color = m_pBlocksMatrix[i][j]-1;
					GetScreenPosFromCell(i, j, iBlockX, iBlockY);
					m_pBlockImg[color]->BlitImage(iBlockX, iBlockY);
				}			
			}
		}

		// Switch the blinking
		if (m_bLineBlinkOn)
			m_bLineBlinkOn = false;
		else
			m_bLineBlinkOn = true;
		m_iLineBlinkCount++;
		// If blink count equals 10, we stop blinking and remove
		// the lines.
		if (m_iLineBlinkCount == 10)
		{
			RemoveLines();
			m_bRemovingLine = false;
			m_bLineBlinkOn = false;
			m_iLineBlinkCount = 0;
			NewShape();
		}
	}
	else 
	{
		// Draw filled blocks
		for (int j=0; j<MATRIX_HEIGHT;j++)
		{
			for (int i=0; i<MATRIX_WIDTH;i++)
			{
				if (m_pBlocksMatrix[i][j])
				{
					int color = m_pBlocksMatrix[i][j]-1;
					GetScreenPosFromCell(i, j, iBlockX, iBlockY);
					m_pBlockImg[color]->BlitImage(iBlockX, iBlockY);
				}
			}
		}

		// Finally, draw the current shape
		if (!m_bGameOver)
			m_pTetrad->Draw();
	}

}

void CBlocksMatrix::Update(DWORD dwCurrentTime)
{
	if (!m_bGameOver)
	{
		// Check if the current shape should be moved down
		if (dwCurrentTime > m_dwLastShapeDown+m_iTetradUpdate)
			ShapeDown();
	}
}

void CBlocksMatrix::ShapeLeft()
{
	if (m_pTetrad)
		m_pTetrad->MoveLeft();
}

void CBlocksMatrix::ShapeRight()
{
	if (m_pTetrad)
		m_pTetrad->MoveRight();
}

void CBlocksMatrix::ShapeDown()
{
	if (m_pTetrad && !m_pTetrad->MoveDown())
	{
		// If the current shape can't move down,
		// we ask it to fill the matrix.
		m_pTetrad->FillMatrix();
		// Then delete the current shape
		delete m_pTetrad;	
		m_pTetrad = NULL;
		
		// We then check if no lines have been completed
		// and create the next shape. The m_bGameOver flag
		// can be set in this NewShape function.
		if (!CheckMatrix())
			NewShape();
	}
	// Set the last update (down) of the shape to 
	// the current time.
	m_dwLastShapeDown = GetCurrentTime();
}

void CBlocksMatrix::NewShape()
{
	m_pTetrad = m_pNextShape;
	m_pNextShape = NULL;
	if (!m_pTetrad->IsValid())
	{
		// If the new shape occupies filled cells,
		// the game is over
		m_bGameOver = true;
		// Inform the listener about it.
		m_pListener->OnMatrixFull();
	}
	else
		m_pNextShape = m_TetradFactory.CreateTetrad(this);
}

void CBlocksMatrix::ShapeRotate()
{
	if (m_pTetrad)
		m_pTetrad->Rotate();
}

bool CBlocksMatrix::IsCellFree(int XPos, int YPos)
{
	if ( (XPos<0) || (XPos>=MATRIX_WIDTH) )
		return false;
	if ( (YPos<0) || (YPos>=MATRIX_HEIGHT) )
		return false;

	if (m_pBlocksMatrix[XPos][YPos] == bcNone)
		return true;
	return false;
}

void CBlocksMatrix::FillCell(int XPos, int YPos, EBlockColor BlockColor)
{
	if ( (XPos<0) || (XPos>=MATRIX_WIDTH) )
		return;
	if ( (YPos<0) || (YPos>=MATRIX_HEIGHT) )
		return;

	m_pBlocksMatrix[XPos][YPos] = BlockColor;
}

void CBlocksMatrix::GetScreenPosFromCell(int cellXPos, 
										 int cellYPos, 
										 int& screenXPos, 
										 int& screenYPos)
{
	screenXPos = m_iXPos + BLOCK_WIDTH * cellXPos;	
	screenYPos = m_iYPos + BLOCK_HEIGHT * cellYPos;	
}

bool CBlocksMatrix::CheckMatrix()
{
	bool bOneLineComplete = false;
	bool bComplete = true;
	// Scan all the lines to see if they are complete
	for (int iRow=0; iRow<MATRIX_HEIGHT;iRow++)
	{
		bComplete = true;
		for (int j=0; j<MATRIX_WIDTH;j++)
		{
			if (m_pBlocksMatrix[j][iRow] == bcNone)
			{
				bComplete = false;
				break;
			}
		}

		// If the current line is complete
		if (bComplete)
		{
			// Push the line index in the vector.
			m_vecLinesRemoved.push_back(iRow);
			// Specify that we switch to the removing line state.
			m_bRemovingLine = true;
			bOneLineComplete = true;
			m_pListener->OnStartRemoveLines();
		}
	}

	return bOneLineComplete;
}

bool CBlocksMatrix::IsLineRemoved(int iRow)
{
	bool bFound = false;
	vector<int>::iterator iter = m_vecLinesRemoved.begin();
	for (iter; iter!=m_vecLinesRemoved.end(); iter++)
	{
		if (iRow == (*iter) )
		{
			bFound = true;
			break;
		}
	}

	return bFound;
}

void CBlocksMatrix::RemoveLines()
{
	vector<int>::iterator iter = m_vecLinesRemoved.begin();
	for (iter; iter!=m_vecLinesRemoved.end();iter++)
	{
		for (int j=0; j<MATRIX_WIDTH;j++)
		{
			// set the current line to empty
			m_pBlocksMatrix[j][(*iter)] = bcNone;

			// Move all the upper blocks one cell down
			for (int iNewRow=(*iter);iNewRow>1;iNewRow--)
			{
				m_pBlocksMatrix[j][iNewRow] = m_pBlocksMatrix[j][iNewRow-1];
			}
		}
	}

	if (m_pListener)
		m_pListener->OnLinesRemoved((int)m_vecLinesRemoved.size());

	m_vecLinesRemoved.clear();
}

CMatrixEventsListener类源码:


// Listener for the blocks matrix
class CMatrixEventsListener
{
public:
	CMatrixEventsListener()  { }
	virtual ~CMatrixEventsListener()  { }

	// Virtual function called when filled lines are
	// detected and will start blinking
	virtual void OnStartRemoveLines() = 0;
	// Virtual function called when the filled lines have
	// been removed
	virtual void OnLinesRemoved(int iLinesCount) = 0;
	// Virtual function called when the game is over.
	virtual void OnMatrixFull() = 0;
};

关于闪烁的原因:

间隔的显示被删除的行,显示在界面上就是方块和背景图案轮流切换,给人一种闪烁的感觉。











Line 334505: M07EF38 05-13 16:47:41.988 985 1172 D audio_hw_primary: start output stream mode:2 devices:2 call_start:1, call_connected:1, is_voip:0, voip_state:0, is_bt_sco:0,out->audio_app_type:0 Line 334516: M07EF43 05-13 16:47:41.989 985 1172 I audio_hw_primary: start vaudio port :0,flags:2,0,0,out->audio_app_type:0 Line 334517: M07EF44 05-13 16:47:41.989 985 1172 W audio_hw_primary: start vaudio_output_stream cp_type is 2 ,card is 2 Line 334825: M07F0DE 05-13 16:47:42.301 985 988 I audio_hw_primary: adev_set_parameters kvpairs : bt_headset_name=Infinix Buds Neo;bt_headset_nrec=off;bt_wbs=on Line 334826: M07F0DF 05-13 16:47:42.301 985 988 I audio_hw_primary: adev_set_parameters bt_wbs on Line 334828: M07F0E1 05-13 16:47:42.301 985 988 V audio_hw_primary: AudioCustom_MmiParse Is OFF Line 334838: M07F0EF 05-13 16:47:42.319 985 988 I audio_hw_primary: adev_set_parameters kvpairs : BT_SCO=on Line 334840: M07F0F1 05-13 16:47:42.319 985 988 V audio_hw_primary: AudioCustom_MmiParse Is OFF Line 335101: M07F228 05-13 16:47:42.487 985 985 W audio_hw_primary: adev_set_voice_volume in...volume:1.000000 mode:2 call_start:1 Line 335102: M07F229 05-13 16:47:42.487 985 985 I audio_hw_primary: at_cmd_volume mode=2 ,volume=8, android vol:1.000000 Line 335103: M07F22A 05-13 16:47:42.487 985 985 V audio_hw_primary: push_voice_command: E Line 335104: M07F22B 05-13 16:47:42.487 985 985 V audio_hw_primary: push_voice_command: at_cmd:AT+VGR=8,bit:1,precmd:,len:32 Line 335105: M07F22C 05-13 16:47:42.487 985 985 E audio_hw_primary: push_voice_command: post:AT+VGR=8,priority:1 Line 335106: M07F22D 05-13 16:47:42.487 985 985 V audio_hw_primary: voice_command_signal: E Line 335107: M07F22E 05-13 16:47:42.487 985 985 E audio_hw_primary: voice_command_signal: X Line 335108: M07F22F 05-13 16:47:42.487 985 985 E audio_hw_primary: push_voice_command: X,at_cmd:AT+VGR=8,bit:1,postcmd:AT+VGR=8 Line 335109: M07F230 05-13 16:47:42.488 985 1046 V audio_hw_primary: do_voice_command: E,332,32,a9392180,dirty:2 Line 335110: M07F231 05-13 16:47:42.488 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty_count:[1] : [9] :[2] Line 335111: M07F232 05-13 16:47:42.488 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty Bit :[1] Line 335112: M07F233 05-13 16:47:42.488 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [2][1][AT+VGR=8][1] Line 335179: M07F297 05-13 16:47:42.534 985 1039 W audio_hw_primary: voice:VBC_CMD_HAL_get_cmd try vbc_lock, pipe_name:/dev/spipe_lte6, ret:12. Line 335180: M07F298 05-13 16:47:42.534 985 1039 W audio_hw_primary: voice: In Call, Get CMD(3) from cp(pipe:/dev/spipe_lte6, pipe_fd:19), paras_size:64 devices:0x2 mode:2 Line 335186: M07F29E 05-13 16:47:42.538 985 1039 I audio_hw_primary: SetVoice_gain_by_devices out, out_devices:0x1, in_devices:0x81000084 Line 335187: M07F29F 05-13 16:47:42.538 985 1039 I audio_hw_primary: SetCall_VolumePara hp_pa_config: 0x1d41, 0x1d41, 0x0,pa_config: 0x694, 0x694, 0x0. Line 335188: M07F2A0 05-13 16:47:42.538 985 1039 I audio_hw_primary: GetCall_VolumePara successfully ,dac_pga_gain_l:0x77 ,dac_pga_gain_r:0x77 ,adc_pga_gain_l:0xf ,adc_pga_gain_r:0xf, devices:0x1 ,mode:2 Line 335193: M07F2A5 05-13 16:47:42.539 985 1039 I audio_hw_primary: SetVoice_gain_by_devices out, out_devices:0x1, in_devices:0x81000084 Line 335194: M07F2A6 05-13 16:47:42.540 985 1039 I audio_hw_primary: Line 335195: M07F2A6 05-13 16:47:42.540 985 1039 I audio_hw_primary: dump_audio_reg:/proc/asound/sprdphone/sprd-codec Line 335196: M07F2A7 05-13 16:47:42.542 985 1039 I audio_hw_primary: read reg size:2047 821 Line 335197: M07F2A8 05-13 16:47:42.542 985 1039 I audio_hw_primary: sc27xx-audio-codec digital part Line 335198: M07F2A9 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0000 | 0x0c0f 0x0000 0x0784 0x03fa Line 335199: M07F2AA 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0010 | 0x0000 0x0008 0x0002 0x0120 Line 335200: M07F2AB 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0020 | 0x0000 0x0000 0x0000 0x0003 Line 335201: M07F2AC 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0030 | 0x0000 0x0019 0x9999 0x0001 Line 335202: M07F2AD 05-13 16:47:42.542 985 1039 I audio_hw_primary: sc27xx-audio-codec analog part(0x403C8700) Line 335203: M07F2AE 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0000 | 0xbc4b 0x832a 0x02ba 0xe429 Line 335204: M07F2AF 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0010 | 0x4800 0x0400 0x5b08 0xf0a0 Line 335205: M07F2B0 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0020 | 0x5fd0 0x1026 0x108c 0x14aa Line 335206: M07F2B1 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0030 | 0x0a02 0xce85 0x00a4 0x0046 Line 335207: M07F2B2 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0040 | 0x0000 0x0000 0x0000 0xffff Line 335208: M07F2B3 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0050 | 0xf000 0x4cd8 0x2e6c 0xa820 Line 335209: M07F2B4 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0060 | 0x0000 0x60c0 0x0100 0x0000 Line 335210: M07F2B5 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0070 | 0x0000 0x0000 0x0000 0x0204 Line 335211: M07F2B6 05-13 16:47:42.542 985 1039 I audio_hw_primary: sc27xx-audio-codec analog part(0x403C8800) Line 335212: M07F2B7 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0000 | 0x0000 0x0000 0x0000 0x0000 Line 335213: M07F2B8 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0010 | 0x0000 0x0000 0x0000 0x0000 Line 335214: M07F2B9 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0020 | 0x001b 0x241a 0xa000 0x001b Line 335215: M07F2BA 05-13 16:47:42.542 985 1039 I audio_hw_primary: 0x0030 | 0x003e 0x0000 0x0017 0x0000 Line 335216: M07F2BB 05-13 16:47:42.542 985 1039 I audio_hw_primary: sc27xx-audio-codec audif(0x403C8140) Line 335217: M07F2BC 05-13 16:47:42.543 985 1039 I audio_hw_primary: 0x0000 | 0x000a 0x0013 0x010d 0x0027 Line 335218: M07F2BD 05-13 16:47:42.543 985 1039 I audio_hw_primary: 0x0010 | 0x0001 0x0000 0x0000 0x0000 Line 335219: M07F2BE 05-13 16:47:42.543 985 1039 W audio_hw_primary: voice:/dev/spipe_lte6, looping now...cur_timeout 0,timeout 0 Line 335221: M07F2C2 05-13 16:47:42.548 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [AT+VGR=8][OK Line 335222: M07F2C2 05-13 16:47:42.548 985 1046 V audio_hw_primary: ] Line 335223: M07F2C3 05-13 16:47:42.548 985 1046 E audio_hw_primary: do_voice_command: X Line 335224: M07F2C4 05-13 16:47:42.548 985 1046 I audio_hw_primary: voice_command_thread_entry looping done. Line 335225: M07F2C5 05-13 16:47:42.548 985 1046 I audio_hw_primary: voice_command_thread_entry looping now... Line 335276: M07F2FC 05-13 16:47:42.584 985 985 I audio_hw_primary: adev_create_audio_patch: source[0] type=2 address= Line 335277: M07F2FD 05-13 16:47:42.584 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_MIX source handle:13 hw_module:10 stream:-1 source:-1 Line 335278: M07F2FE 05-13 16:47:42.584 985 985 D audio_hw_primary: source audio_port_config id:1 role:1 type:2 config_mask:7 sample_rate:44100 channel_mask id:3 format:1 Line 335279: M07F300 05-13 16:47:42.584 985 985 D audio_hw_primary: source gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 335280: M07F301 05-13 16:47:42.584 985 985 D audio_hw_primary: source gain[0]:0x0 Line 335281: M07F302 05-13 16:47:42.584 985 985 D audio_hw_primary: source gain[1]:0x0 Line 335282: M07F303 05-13 16:47:42.584 985 985 I audio_hw_primary: adev_create_audio_patch: sink[0] type=1 address=41:42:F1:39:D7:E9 Line 335283: M07F304 05-13 16:47:42.584 985 985 I audio_hw_primary: :device:20 Line 335284: M07F305 05-13 16:47:42.584 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_DEVICE sink device type:0x20 hw_module:10 Line 335285: M07F306 05-13 16:47:42.584 985 985 D audio_hw_primary: sink audio_port_config id:159 role:2 type:1 config_mask:7 sample_rate:16000 channel_mask id:1 format:1 Line 335286: M07F307 05-13 16:47:42.584 985 985 D audio_hw_primary: sink gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 335287: M07F308 05-13 16:47:42.584 985 985 D audio_hw_primary: sink gain[0]:0x0 Line 335288: M07F309 05-13 16:47:42.584 985 985 I audio_hw_primary: adev_set_out_devices device is 2,20 Line 335289: M07F30A 05-13 16:47:42.584 985 985 I audio_hw_primary: adev_check_out_devices 0xa939a380 2 32 Line 335290: M07F30B 05-13 16:47:42.584 985 985 I audio_hw_primary: adev_check_out_devices 0xa939a540 2 32 Line 335291: M07F30C 05-13 16:47:42.584 985 985 I audio_hw_primary: select_devices_signal starting... adev->out_devices 0x20 adev->in_devices 0x80000008 Line 335292: M07F30D 05-13 16:47:42.585 985 985 I audio_hw_primary: select_devices_signal finished. Line 335293: M07F30E 05-13 16:47:42.585 985 985 V audio_hw_primary: push_voice_command: E Line 335294: M07F30F 05-13 16:47:42.585 985 1044 V audio_hw_primary: do_select_devices E Line 335295: M07F310 05-13 16:47:42.585 985 985 V audio_hw_primary: push_voice_command: at_cmd:AT+SSAM=64,bit:7,precmd:,len:32 Line 335296: M07F311 05-13 16:47:42.585 985 985 E audio_hw_primary: push_voice_command: post:AT+SSAM=64,priority:1 Line 335297: M07F312 05-13 16:47:42.585 985 985 V audio_hw_primary: voice_command_signal: E Line 335298: M07F313 05-13 16:47:42.585 985 1046 V audio_hw_primary: do_voice_command: E,332,32,a9392180,dirty:80 Line 335299: M07F314 05-13 16:47:42.585 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty_count:[1] : [9] :[80] Line 335300: M07F315 05-13 16:47:42.585 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty Bit :[7] Line 335301: M07F316 05-13 16:47:42.585 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [2][1][AT+SSAM=64][7] Line 335302: M07F317 05-13 16:47:42.585 985 1046 W audio_hw_primary: at_cmd_routeDev AT+SSAM=64 routeDev:0 Line 335303: M07F319 05-13 16:47:42.585 985 985 E audio_hw_primary: voice_command_signal: X Line 335304: M07F31A 05-13 16:47:42.585 985 985 E audio_hw_primary: push_voice_command: X,at_cmd:AT+SSAM=64,bit:7,postcmd: Line 335336: M07F33F 05-13 16:47:42.596 985 985 V audio_hw_primary: push_route_command: E Line 335339: M07F342 05-13 16:47:42.596 985 985 E audio_hw_primary: push_route_command: at_cmd:AT+SSAM=6,bit:0,precmd:,len:32 Line 335341: M07F344 05-13 16:47:42.596 985 985 E audio_hw_primary: push_route_command: post:AT+SSAM=6,priority:1 Line 335342: M07F345 05-13 16:47:42.596 985 985 V audio_hw_primary: voice_command_signal: E Line 335344: M07F347 05-13 16:47:42.596 985 985 E audio_hw_primary: voice_command_signal: X Line 335345: M07F348 05-13 16:47:42.596 985 985 E audio_hw_primary: push_route_command: X,at_cmd:AT+SSAM=6,bit:0,postcmd:AT+SSAM=6 Line 335354: M07F352 05-13 16:47:42.597 985 985 D audio_hw_primary: adev_set_out_devices want to set devices:0x20 mode:2 call_start:1 Line 335355: M07F354 05-13 16:47:42.601 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [AT+SSAM=64][OK Line 335356: M07F354 05-13 16:47:42.601 985 1046 V audio_hw_primary: ] Line 335357: M07F355 05-13 16:47:42.601 985 1046 E audio_hw_primary: do_voice_command: X Line 335358: M07F356 05-13 16:47:42.601 985 1046 I audio_hw_primary: voice_command_thread_entry looping done. Line 335359: M07F357 05-13 16:47:42.601 985 1046 I audio_hw_primary: voice_command_thread_entry looping now... Line 335360: M07F358 05-13 16:47:42.601 985 1046 V audio_hw_primary: do_voice_command: E,332,32,a9392180,dirty:1 Line 335361: M07F359 05-13 16:47:42.601 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty_count:[1] : [9] :[1] Line 335362: M07F35A 05-13 16:47:42.601 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty Bit :[0] Line 335363: M07F35B 05-13 16:47:42.601 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [2][1][AT+SSAM=6][0] Line 335364: M07F35C 05-13 16:47:42.602 985 1046 W audio_hw_primary: at_cmd_routeDev AT+SSAM=6 routeDev:20 Line 335366: M07F35F 05-13 16:47:42.604 985 985 D audio_hw_primary: adev_create_audio_patch: handle: 108 Line 335367: M07F360 05-13 16:47:42.605 985 1044 I audio_hw_primary: cache_mute=0 ,mastermute=0 Line 335368: M07F361 05-13 16:47:42.605 985 1044 I audio_hw_primary: Not to change mute: 0 Line 335369: M07F362 05-13 16:47:42.605 985 1044 I audio_hw_primary: stream_routing_thread looping done. Line 335370: M07F363 05-13 16:47:42.605 985 1044 I audio_hw_primary: stream_routing_thread looping now... Line 335376: M07F370 05-13 16:47:42.633 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [AT+SSAM=6][OK Line 335377: M07F370 05-13 16:47:42.633 985 1046 V audio_hw_primary: ] Line 335378: M07F371 05-13 16:47:42.633 985 1046 E audio_hw_primary: do_voice_command: X Line 335379: M07F372 05-13 16:47:42.633 985 1046 I audio_hw_primary: voice_command_thread_entry looping done. Line 335380: M07F373 05-13 16:47:42.633 985 1046 I audio_hw_primary: voice_command_thread_entry looping now... Line 335385: M07F384 05-13 16:47:42.664 985 985 I audio_hw_primary: adev_create_audio_patch: source[0] type=2 address= Line 335386: M07F385 05-13 16:47:42.664 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_MIX source handle:13 hw_module:10 stream:-1 source:-1 Line 335387: M07F386 05-13 16:47:42.664 985 985 D audio_hw_primary: source audio_port_config id:1 role:1 type:2 config_mask:7 sample_rate:44100 channel_mask id:3 format:1 Line 335388: M07F387 05-13 16:47:42.664 985 985 D audio_hw_primary: source gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 335389: M07F388 05-13 16:47:42.665 985 985 D audio_hw_primary: source gain[0]:0x0 Line 335390: M07F389 05-13 16:47:42.665 985 985 D audio_hw_primary: source gain[1]:0x0 Line 335391: M07F38A 05-13 16:47:42.665 985 985 I audio_hw_primary: adev_create_audio_patch: sink[0] type=1 address=41:42:F1:39:D7:E9 Line 335392: M07F38B 05-13 16:47:42.665 985 985 I audio_hw_primary: :device:20 Line 335393: M07F38C 05-13 16:47:42.665 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_DEVICE sink device type:0x20 hw_module:10 Line 335394: M07F38D 05-13 16:47:42.665 985 985 D audio_hw_primary: sink audio_port_config id:159 role:2 type:1 config_mask:7 sample_rate:16000 channel_mask id:1 format:1 Line 335395: M07F38E 05-13 16:47:42.665 985 985 D audio_hw_primary: sink gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 335396: M07F38F 05-13 16:47:42.665 985 985 D audio_hw_primary: sink gain[0]:0x0 Line 335397: M07F390 05-13 16:47:42.665 985 985 I audio_hw_primary: adev_set_out_devices device is 20,20 Line 335398: M07F391 05-13 16:47:42.665 985 985 I audio_hw_primary: adev_check_out_devices 0xa939a380 32 32 Line 335399: M07F392 05-13 16:47:42.665 985 985 I audio_hw_primary: adev_check_out_devices 0xa939a540 32 32 Line 335400: M07F393 05-13 16:47:42.665 985 985 I audio_hw_primary: select_devices_signal starting... adev->out_devices 0x20 adev->in_devices 0x80000008 Line 335401: M07F394 05-13 16:47:42.665 985 985 I audio_hw_primary: select_devices_signal finished. Line 335402: M07F395 05-13 16:47:42.665 985 985 V audio_hw_primary: push_voice_command: E Line 335403: M07F396 05-13 16:47:42.665 985 985 V audio_hw_primary: push_voice_command: at_cmd:AT+SSAM=64,bit:7,precmd:,len:32 Line 335404: M07F397 05-13 16:47:42.665 985 985 E audio_hw_primary: push_voice_command: post:AT+SSAM=64,priority:1 Line 335405: M07F398 05-13 16:47:42.665 985 985 V audio_hw_primary: voice_command_signal: E Line 335406: M07F399 05-13 16:47:42.665 985 985 E audio_hw_primary: voice_command_signal: X Line 335407: M07F39A 05-13 16:47:42.665 985 985 E audio_hw_primary: push_voice_command: X,at_cmd:AT+SSAM=64,bit:7,postcmd:AT+SSAM=64 Line 335408: M07F39B 05-13 16:47:42.665 985 1046 V audio_hw_primary: do_voice_command: E,332,32,a9392180,dirty:80 Line 335409: M07F39C 05-13 16:47:42.665 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty_count:[1] : [9] :[80] Line 335410: M07F39D 05-13 16:47:42.665 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty Bit :[7] Line 335411: M07F39E 05-13 16:47:42.665 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [2][1][AT+SSAM=64][7] Line 335412: M07F39F 05-13 16:47:42.665 985 1046 W audio_hw_primary: at_cmd_routeDev AT+SSAM=64 routeDev:0 Line 335413: M07F3AB 05-13 16:47:42.673 985 1044 V audio_hw_primary: do_select_devices E Line 335414: M07F3AD 05-13 16:47:42.673 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [AT+SSAM=64][OK Line 335415: M07F3AD 05-13 16:47:42.673 985 1046 V audio_hw_primary: ] Line 335416: M07F3AE 05-13 16:47:42.674 985 1046 E audio_hw_primary: do_voice_command: X Line 335417: M07F3AF 05-13 16:47:42.674 985 1046 I audio_hw_primary: voice_command_thread_entry looping done. Line 335418: M07F3B0 05-13 16:47:42.674 985 1046 I audio_hw_primary: voice_command_thread_entry looping now... Line 335419: M07F3B1 05-13 16:47:42.676 985 985 V audio_hw_primary: push_route_command: E Line 335420: M07F3B2 05-13 16:47:42.676 985 985 E audio_hw_primary: push_route_command: at_cmd:AT+SSAM=6,bit:0,precmd:,len:32 Line 335421: M07F3B3 05-13 16:47:42.676 985 985 E audio_hw_primary: push_route_command: post:AT+SSAM=6,priority:1 Line 335422: M07F3B4 05-13 16:47:42.676 985 985 V audio_hw_primary: voice_command_signal: E Line 335423: M07F3B5 05-13 16:47:42.676 985 985 E audio_hw_primary: voice_command_signal: X Line 335424: M07F3B6 05-13 16:47:42.676 985 985 E audio_hw_primary: push_route_command: X,at_cmd:AT+SSAM=6,bit:0,postcmd:AT+SSAM=6 Line 335425: M07F3B7 05-13 16:47:42.676 985 985 D audio_hw_primary: adev_set_out_devices want to set devices:0x20 mode:2 call_start:1 Line 335426: M07F3B8 05-13 16:47:42.676 985 1046 V audio_hw_primary: do_voice_command: E,332,32,a9392180,dirty:1 Line 335427: M07F3B9 05-13 16:47:42.676 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty_count:[1] : [9] :[1] Line 335428: M07F3BA 05-13 16:47:42.676 985 985 D audio_hw_primary: adev_create_audio_patch: handle: 109 Line 335429: M07F3BB 05-13 16:47:42.676 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty Bit :[0] Line 335430: M07F3BC 05-13 16:47:42.676 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [2][1][AT+SSAM=6][0] Line 335431: M07F3BD 05-13 16:47:42.676 985 1046 W audio_hw_primary: at_cmd_routeDev AT+SSAM=6 routeDev:20 Line 335432: M07F3BF 05-13 16:47:42.679 985 985 I audio_hw_primary: adev_create_audio_patch: source[0] type=2 address= Line 335433: M07F3C0 05-13 16:47:42.679 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_MIX source handle:13 hw_module:10 stream:-1 source:-1 Line 335434: M07F3C1 05-13 16:47:42.679 985 985 D audio_hw_primary: source audio_port_config id:1 role:1 type:2 config_mask:7 sample_rate:44100 channel_mask id:3 format:1 Line 335435: M07F3C2 05-13 16:47:42.680 985 985 D audio_hw_primary: source gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 335436: M07F3C3 05-13 16:47:42.680 985 985 D audio_hw_primary: source gain[0]:0x0 Line 335437: M07F3C4 05-13 16:47:42.680 985 985 D audio_hw_primary: source gain[1]:0x0 Line 335438: M07F3C5 05-13 16:47:42.680 985 985 I audio_hw_primary: adev_create_audio_patch: sink[0] type=1 address=41:42:F1:39:D7:E9 Line 335439: M07F3C6 05-13 16:47:42.680 985 985 I audio_hw_primary: :device:20 Line 335440: M07F3C7 05-13 16:47:42.680 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_DEVICE sink device type:0x20 hw_module:10 Line 335441: M07F3C8 05-13 16:47:42.680 985 985 D audio_hw_primary: sink audio_port_config id:159 role:2 type:1 config_mask:7 sample_rate:16000 channel_mask id:1 format:1 Line 335442: M07F3C9 05-13 16:47:42.680 985 985 D audio_hw_primary: sink gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 335443: M07F3CA 05-13 16:47:42.680 985 985 D audio_hw_primary: sink gain[0]:0x0 Line 335444: M07F3CC 05-13 16:47:42.680 985 985 I audio_hw_primary: adev_set_out_devices device is 20,20 Line 335445: M07F3D3 05-13 16:47:42.682 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [AT+SSAM=6][OK Line 335446: M07F3D3 05-13 16:47:42.682 985 1046 V audio_hw_primary: ] Line 335447: M07F3D4 05-13 16:47:42.682 985 1046 E audio_hw_primary: do_voice_command: X Line 335448: M07F3D5 05-13 16:47:42.682 985 1046 I audio_hw_primary: voice_command_thread_entry looping done. Line 335449: M07F3D6 05-13 16:47:42.682 985 1046 I audio_hw_primary: voice_command_thread_entry looping now... Line 335452: M07F3D9 05-13 16:47:42.696 985 985 I audio_hw_primary: adev_check_out_devices 0xa939a380 32 32 Line 335453: M07F3DA 05-13 16:47:42.697 985 985 I audio_hw_primary: adev_check_out_devices 0xa939a540 32 32 Line 335454: M07F3DB 05-13 16:47:42.697 985 985 I audio_hw_primary: select_devices_signal starting... adev->out_devices 0x20 adev->in_devices 0x80000008 Line 335455: M07F3DC 05-13 16:47:42.697 985 985 I audio_hw_primary: select_devices_signal finished. Line 335456: M07F3DD 05-13 16:47:42.697 985 985 V audio_hw_primary: push_voice_command: E Line 335457: M07F3DE 05-13 16:47:42.697 985 985 V audio_hw_primary: push_voice_command: at_cmd:AT+SSAM=64,bit:7,precmd:,len:32 Line 335458: M07F3DF 05-13 16:47:42.697 985 985 E audio_hw_primary: push_voice_command: post:AT+SSAM=64,priority:1 Line 335459: M07F3E0 05-13 16:47:42.697 985 985 V audio_hw_primary: voice_command_signal: E Line 335461: M07F3E2 05-13 16:47:42.697 985 985 E audio_hw_primary: voice_command_signal: X Line 335462: M07F3E3 05-13 16:47:42.697 985 985 E audio_hw_primary: push_voice_command: X,at_cmd:AT+SSAM=64,bit:7,postcmd:AT+SSAM=64 Line 335463: M07F3E4 05-13 16:47:42.697 985 1046 V audio_hw_primary: do_voice_command: E,332,32,a9392180,dirty:80 Line 335464: M07F3E5 05-13 16:47:42.697 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty_count:[1] : [9] :[80] Line 335465: M07F3E6 05-13 16:47:42.697 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty Bit :[7] Line 335466: M07F3E7 05-13 16:47:42.697 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [2][1][AT+SSAM=64][7] Line 335467: M07F3E8 05-13 16:47:42.697 985 1046 W audio_hw_primary: at_cmd_routeDev AT+SSAM=64 routeDev:0 Line 335470: M07F3F3 05-13 16:47:42.707 985 985 V audio_hw_primary: push_route_command: E Line 335471: M07F3F4 05-13 16:47:42.707 985 985 E audio_hw_primary: push_route_command: at_cmd:AT+SSAM=6,bit:0,precmd:,len:32 Line 335472: M07F3F5 05-13 16:47:42.707 985 985 E audio_hw_primary: push_route_command: post:AT+SSAM=6,priority:1 Line 335473: M07F3F6 05-13 16:47:42.707 985 985 V audio_hw_primary: voice_command_signal: E Line 335474: M07F3F7 05-13 16:47:42.707 985 985 E audio_hw_primary: voice_command_signal: X Line 335475: M07F3F8 05-13 16:47:42.707 985 985 E audio_hw_primary: push_route_command: X,at_cmd:AT+SSAM=6,bit:0,postcmd:AT+SSAM=6 Line 335476: M07F3F9 05-13 16:47:42.708 985 985 D audio_hw_primary: adev_set_out_devices want to set devices:0x20 mode:2 call_start:1 Line 335477: M07F3FA 05-13 16:47:42.708 985 1044 I audio_hw_primary: cache_mute=0 ,mastermute=0 Line 335478: M07F3FB 05-13 16:47:42.709 985 1044 I audio_hw_primary: Not to change mute: 0 Line 335479: M07F3FC 05-13 16:47:42.709 985 1044 I audio_hw_primary: stream_routing_thread looping done. Line 335480: M07F3FD 05-13 16:47:42.709 985 1044 I audio_hw_primary: stream_routing_thread looping now... Line 335481: M07F3FE 05-13 16:47:42.709 985 1044 V audio_hw_primary: do_select_devices E Line 335482: M07F3FF 05-13 16:47:42.709 985 1044 I audio_hw_primary: cache_mute=0 ,mastermute=0 Line 335483: M07F400 05-13 16:47:42.709 985 1044 I audio_hw_primary: Not to change mute: 0 Line 335484: M07F401 05-13 16:47:42.709 985 1044 I audio_hw_primary: stream_routing_thread looping done. Line 335485: M07F402 05-13 16:47:42.709 985 1044 I audio_hw_primary: stream_routing_thread looping now... Line 335486: M07F403 05-13 16:47:42.710 985 985 D audio_hw_primary: adev_create_audio_patch: handle: 110 Line 335487: M07F404 05-13 16:47:42.710 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [AT+SSAM=64][OK Line 335488: M07F404 05-13 16:47:42.710 985 1046 V audio_hw_primary: ] Line 335489: M07F405 05-13 16:47:42.710 985 1046 E audio_hw_primary: do_voice_command: X Line 335490: M07F406 05-13 16:47:42.710 985 1046 I audio_hw_primary: voice_command_thread_entry looping done. Line 335491: M07F407 05-13 16:47:42.711 985 1046 I audio_hw_primary: voice_command_thread_entry looping now... Line 335492: M07F408 05-13 16:47:42.711 985 1046 V audio_hw_primary: do_voice_command: E,332,32,a9392180,dirty:1 Line 335493: M07F409 05-13 16:47:42.711 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty_count:[1] : [9] :[1] Line 335494: M07F40A 05-13 16:47:42.711 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command dirty Bit :[0] Line 335495: M07F40B 05-13 16:47:42.711 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [2][1][AT+SSAM=6][0] Line 335496: M07F40C 05-13 16:47:42.711 985 1046 W audio_hw_primary: at_cmd_routeDev AT+SSAM=6 routeDev:20 Line 335504: M07F41C 05-13 16:47:42.725 985 1046 V audio_hw_primary: do_cmd_dual Switch incall AT command [AT+SSAM=6][OK Line 335505: M07F41C 05-13 16:47:42.725 985 1046 V audio_hw_primary: ] Line 335506: M07F41D 05-13 16:47:42.725 985 1046 E audio_hw_primary: do_voice_command: X Line 335507: M07F41E 05-13 16:47:42.725 985 1046 I audio_hw_primary: voice_command_thread_entry looping done. Line 335508: M07F41F 05-13 16:47:42.725 985 1046 I audio_hw_primary: voice_command_thread_entry looping now... Line 335784: M07F5B0 05-13 16:47:44.657 985 985 V audio_hw_primary: do_output_standby in 0 Line 335785: M07F5B1 05-13 16:47:44.657 985 985 W audio_hw_primary: do_output_standby.mode:2 Line 335787: M07F5B3 05-13 16:47:44.658 985 985 V audio_hw_primary: do_output_standby in out Line 335798: M07F5D4 05-13 16:47:45.003 985 985 I audio_hw_primary: adev_set_parameters kvpairs : policy_force_fm_mute=0 Line 335799: M07F5D5 05-13 16:47:45.003 985 985 I audio_hw_primary: set_fm_mute, mute:0 Line 335801: M07F5D7 05-13 16:47:45.004 985 985 V audio_hw_primary: AudioCustom_MmiParse Is OFF Line 335846: M07F60A 05-13 16:47:45.479 985 1172 D audio_hw_primary: start output stream mode:2 devices:20 call_start:1, call_connected:1, is_voip:0, voip_state:0, is_bt_sco:0,out->audio_app_type:0 Line 335855: M07F613 05-13 16:47:45.480 985 1172 I audio_hw_primary: start vaudio port :0,flags:2,0,0,out->audio_app_type:0 Line 335856: M07F614 05-13 16:47:45.480 985 1172 W audio_hw_primary: start vaudio_output_stream cp_type is 2 ,card is 2 Line 335925: M07F677 05-13 16:47:45.863 985 985 I audio_hw_primary: adev_set_parameters kvpairs : play_sprd_record_tone=1 Line 335926: M07F678 05-13 16:47:45.863 985 985 I audio_hw_primary: adev_set_parameters, record tone by output, value:1, call_connected:1 Line 335927: M07F679 05-13 16:47:45.863 985 985 I audio_hw_primary: yaye adev_record_tone_start, entry!!! Line 335928: M07F67A 05-13 16:47:45.863 985 985 V audio_hw_primary: do_output_standby in 0 Line 335929: M07F67B 05-13 16:47:45.863 985 985 W audio_hw_primary: do_output_standby.mode:2 Line 335931: M07F67D 05-13 16:47:45.864 985 985 V audio_hw_primary: do_output_standby in out Line 335932: M07F67E 05-13 16:47:45.864 985 985 E audio_hw_primary: yaye audio_get_cp_card_name name:saudiolte Line 335942: M07F688 05-13 16:47:45.865 985 985 I audio_hw_primary: yaye adev_record_tone_start, exit!!! Line 335944: M07F68A 05-13 16:47:45.865 985 985 V audio_hw_primary: AudioCustom_MmiParse Is OFF Line 335951: M07F691 05-13 16:47:45.867 985 1172 D audio_hw_primary: YAYE: out_bypass_data mixer_to_cp_uplink!!! Line 335959: M07F699 05-13 16:47:45.879 985 985 I audio_hw_primary: adev_open_input_stream,devices=0x80000008,sample_rate=8000, channel_count=1 source:1 Line 335960: M07F69A 05-13 16:47:45.879 985 1172 D audio_hw_primary: YAYE: out_bypass_data mixer_to_cp_uplink!!! Line 335961: M07F69B 05-13 16:47:45.879 985 985 I audio_hw_primary: Successfully, adev_open_input_stream. Line 335964: M07F69E 05-13 16:47:45.891 985 1172 D audio_hw_primary: YAYE: out_bypass_data mixer_to_cp_uplink!!! Line 335977: M07F6AE 05-13 16:47:45.904 985 1172 D audio_hw_primary: start output stream mode:2 devices:20 call_start:1, call_connected:1, is_voip:0, voip_state:0, is_bt_sco:0,out->audio_app_type:0 Line 335988: M07F6B9 05-13 16:47:45.905 985 1172 I audio_hw_primary: start vaudio port :0,flags:2,0,0,out->audio_app_type:0 Line 335989: M07F6BA 05-13 16:47:45.905 985 1172 W audio_hw_primary: start vaudio_output_stream cp_type is 2 ,card is 2 Line 336084: M07F707 05-13 16:47:45.984 985 985 I audio_hw_primary: adev_create_audio_patch: source[0] type=1 address=41:42:F1:39:D7:E9 Line 336085: M07F708 05-13 16:47:45.984 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_DEVICE source device type:0x80000008 hw_module:10 Line 336087: M07F70A 05-13 16:47:45.984 985 985 D audio_hw_primary: source audio_port_config id:160 role:1 type:1 config_mask:7 sample_rate:16000 channel_mask id:16 format:1 Line 336088: M07F70B 05-13 16:47:45.984 985 985 D audio_hw_primary: source gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 336089: M07F70C 05-13 16:47:45.984 985 985 D audio_hw_primary: source gain[0]:0x0 Line 336090: M07F70E 05-13 16:47:45.984 985 985 I audio_hw_primary: adev_create_audio_patch: sink[0] type=2 address=N/A Line 336091: M07F70F 05-13 16:47:45.984 985 985 I audio_hw_primary: :device:5e Line 336092: M07F710 05-13 16:47:45.984 985 985 I audio_hw_primary: AUDIO_PORT_TYPE_MIX sink handle:94 hw_module:10 stream:1 source:1 Line 336093: M07F711 05-13 16:47:45.984 985 985 D audio_hw_primary: sink audio_port_config id:167 role:2 type:2 config_mask:7 sample_rate:8000 channel_mask id:16 format:1 Line 336094: M07F712 05-13 16:47:45.984 985 985 D audio_hw_primary: sink gain index:-1 mode:0x0 channel_mask:0x0 ramp_duration_ms:0 Line 336095: M07F713 05-13 16:47:45.984 985 985 D audio_hw_primary: sink gain[0]:0x0 Line 336096: M07F717 05-13 16:47:45.985 985 985 I audio_hw_primary: adev_set_in_devices device is 80000008,80000008 Line 336097: M07F718 05-13 16:47:45.985 985 985 I audio_hw_primary: select_devices_signal starting... adev->out_devices 0x20 adev->in_devices 0x80000008 Line 336098: M07F719 05-13 16:47:45.985 985 985 I audio_hw_primary: select_devices_signal finished. Line 336099: M07F71A 05-13 16:47:45.985 985 985 I audio_hw_primary: adev_set_in_pop_mute Line 336100: M07F71B 05-13 16:47:45.985 985 1044 V audio_hw_primary: do_select_devices E Line 336101: M07F71C 05-13 16:47:45.985 985 985 D audio_hw_primary: adev_create_audio_patch: handle: 111 Line 336102: M07F71D 05-13 16:47:45.985 985 1044 I audio_hw_primary: cache_mute=0 ,mastermute=0 Line 336103: M07F71E 05-13 16:47:45.985 985 1044 I audio_hw_primary: Not to change mute: 0 Line 336104: M07F71F 05-13 16:47:45.986 985 1044 I audio_hw_primary: stream_routing_thread looping done. Line 336106: M07F721 05-13 16:47:45.986 985 1044 I audio_hw_primary: stream_routing_thread looping now... Line 336116: M07F735 05-13 16:47:46.003 985 988 V audio_hw_primary: in_set_microphone_field_dimension() Line 336119: M07F738 05-13 16:47:46.005 985 9836 W audio_hw_primary: start_input_stream in mode:2 devices:80000008 call_start:1, is_voip:0, is_bt_sco:0, adev->fm_open 0 adev->fm_record 0,is_fm_rec:0,fm_uldl:0,in->device:80000008,active input:0, in->source:1 Line 336126: M07F73F 05-13 16:47:46.006 985 9836 I audio_hw_primary: start voice_rx AUDIO_SOURCE_VOICE_CALL Line 336127: M07F740 05-13 16:47:46.007 985 9836 I audio_hw_primary: start_input,channels=1,peroid_size=320, peroid_count=8,rate=8000 Line 336129: M07F742 05-13 16:47:46.007 985 9836 I audio_hw_primary: start input stream out Line 336149: M07F757 05-13 16:47:46.037 985 9836 I audio_hw_primary: set mute in_read bytes 640 in->pop_mute_bytes 3200 Line 336155: M07F75D 05-13 16:47:46.075 985 9836 I audio_hw_primary: set mute in_read bytes 640 in->pop_mute_bytes 2560 Line 336156: M07F75E 05-13 16:47:46.116 985 9836 I audio_hw_primary: set mute in_read bytes 640 in->pop_mute_bytes 1920 Line 336157: M07F75F 05-13 16:47:46.156 985 9836 I audio_hw_primary: set mute in_read bytes 640 in->pop_mute_bytes 1280 Line 336158: M07F760 05-13 16:47:46.195 985 9836 I audio_hw_primary: set mute in_read bytes 640 in->pop_mute_bytes 640 Line 336187: M07F7B1 05-13 16:47:48.590 985 988 V audio_hw_primary: do_output_standby in 0 Line 336188: M07F7B2 05-13 16:47:48.590 985 988 W audio_hw_primary: do_output_standby.mode:2 Line 336190: M07F7B4 05-13 16:47:48.591 985 988 V audio_hw_primary: do_output_standby in out Line 336532: M07F9D6 05-13 16:48:20.698 985 1172 D audio_hw_primary: start output stream mode:2 devices:20 call_start:1, call_connected:1, is_voip:0, voip_state:0, is_bt_sco:0,out->audio_app_type:0分析log
最新发布
05-14
<think>嗯,用户提供了一段Android音频系统的日志,并希望分析这些日志。首先,我需要理解这些日志的结构和内容。看起来这些日志来自audio_hw_primary模块,涉及到音频流的启动、设备切换、AT命令处理等。 首先,用户可能遇到了音频相关的问题,比如通话中的音频路由问题,或者设备切换不正常。用户可能想知道这些日志中的错误或警告信息的原因,或者想确认音频配置是否正确。 日志中多次出现`startoutput stream`,说明有音频输出流被创建,设备类型是0x20,即蓝牙设备。同时,处理AT命令如`AT+VGR=8`和`AT+SSAM=64`,这些可能用于调整音量和路由设置。出现了一些警告,比如`W audio_hw_primary:start vaudio_output_stream cp_type is2 ,cardis 2`,这可能表示音频路径配置的问题。接下来,我需要分析关键部分。例如,`adev_set_parameters`用于设置参数,如蓝牙设备名称和宽频语音(WBS)开启。`push_voice_command`处理AT命令,涉及优先级和路由设备切换,可能有错误处理不当的情况。 另外,日志中有`select_devices_signal`的调用,这可能涉及音频设备的选择逻辑,检查设备切换是否正常。`do_output_standby`多次出现,可能涉及音频流的停止和资源释放,需要确认是否有异常。用户可能需要了解这些日志中的错误和警告具体含义,以及如何解决可能的音频问题。例如,AT命令执行是否成功,设备切换是否生效,或者是否存在配置错误导致音频路由失败。此外,用户可能想知道如何调试音频硬件抽象层(HAL)的问题,或者如何验证音频配置是否正确。 最后,根据用户之前的提问历史,他们可能在进行系统级调试,尤其是音频模块,可能需要进一步的日志分析或代码层面的检查。用户可能需要指导如何捕捉更多相关日志,或者如何修改HAL代码以解决问题。</think>从日志分析来看,这属于Android音频子系统(audio HAL)的处理过程,主要涉及通话场景下的蓝牙音频设备交互。以下是关键点解析: 1. **蓝牙设备交互**: ```log adev_set_parameters bt_wbs on // 启用了蓝牙宽频语音 bt_headset_name=Infinix Buds Neo // 连接的蓝牙设备名称 ``` 2. **音频路由控制**: ```log AT+SSAM=64 // 音频路由切换命令 at_cmd_routeDev AT+SSAM=64 routeDev:0 // 路由到默认设备 at_cmd_routeDev AT+SSAM=6 routeDev:20 // 路由到蓝牙设备(0x20对应AUDIO_DEVICE_OUT_BLUETOOTH_SCO) ``` 3. **语音增益控制**: ```log AT+VGR=8 // 语音增益设置命令 at_cmd_volume mode=2 ,volume=8 // 通话模式下的音量设置 ``` 4. **寄存器调试信息**: ```log dump_audio_reg:/proc/asound/sprdphone/sprd-codec // 输出了音频编解码器寄存器状态 read reg size:2047 821 // 寄存器读取操作 ``` 5. **音频流生命周期: ```log start_output_stream mode:2 devices:2 // 启动音频输出流(MODE_IN_CALL) do_output_standby in 0 // 停止音频输出流 ``` 根本原因可能是蓝牙音频设备在通话中的路由切换存在问题。建议检查以下Java层相关代码: ```java // 蓝牙设备连接状态监听 BluetoothAdapter.getProfileProxy(context, new BluetoothProfile.ServiceListener() { @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { // 处理设备连接状态变化 } }, BluetoothProfile.HEADSET); // 音频路由控制 AudioManager.setBluetoothScoOn(true); AudioManager.startBluetoothSco(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值